在.Net Core 2.0,ASP.Net react项目中使用Linq时,我遇到了一个非常奇怪的行为:
访问在Linq“选择”选择器中实例化的对象的字段时,它将引发“访问冲突异常”
希望复制的步骤:
按如下所示更改 SampleDataController.cs :
[HttpGet("[action]")]
public string Objects()
{
var rng = new Random();
var ret = Enumerable.Range(1, 5).Select(index =>
new TableDef("User")
.AddField(new StringField("ID", Guid.NewGuid().ToString()))
.AddField(new StringField("Name", "User " + index.ToString()))
);
return "[" +
ret.Select(x => x.ToJSONString()).Aggregate((current, next) => current + ", " + next) +
"]";
}
具有以下类别:
public class TableDef
{
public string ID { get; private set; } = Guid.NewGuid().ToString();
public string LockedBy { get; private set; } = "";
public string Name { get; private set; }
public FieldDef[] Fields { get; private set; }
public TableDef(string name)
{
Name = name;
Fields = new FieldDef[0];
}
public TableDef AddField(FieldDef field)
{
field.Parent = this;
var flds = this.Fields;
Array.Resize(ref flds, flds.Length + 1);
flds[flds.Length - 1] = field;
this.Fields = flds;
return this;
}
public string ToJSONString()
{
return @" { ""TableDef"": {""
""DefID"": """ + ID + @""",
""DefName"": """ + Name + @""",
""DefLockedBy"": """ + LockedBy + @"""}, " +
Fields
.Select(x => ('"' + x.Name + @""" : """ + x.Value + '"'))
.Aggregate((current, next) => current + ", " + next) +
"}";
}
}
public abstract class FieldDef
{
public string ID { get; protected set; } = Guid.NewGuid().ToString();
public string Name { get; protected set; }
public abstract string Value { get; set; }
public abstract string DefaultValue { get; set; }
public Boolean ReadOnly { get; protected set; } = false;
public Boolean IsDirty { get; set; } = false;
public TableDef Parent {
get { return Parent; }
set {
this.Parent = value;
ID = Parent.Name.Replace(" ", "") + "_" + Name.Replace(" ", "");
}
}
}
public class StringField : FieldDef
{
public override string Value {
get { return (IsDirty) ? Value : DefaultValue; }
set { this.Value = value; }
}
public override string DefaultValue { get; set; }
public StringField(string name, string defaultValue)
{
Name = name;
DefaultValue = defaultValue;
}
public StringField(string name, string defaultValue, Boolean readOnly)
{
Name = name;
DefaultValue = defaultValue;
ReadOnly = readOnly;
}
}
运行代码并单击“获取数据”链接时,该应用程序完全消失(至少在我看来是这样),而在Visual Studio中甚至没有错误。调试刚刚结束,剩下以下调试输出:
The program '[20584] dotnet.exe: Program Trace' has exited with code 0 (0x0).
The program '[20584] dotnet.exe' has exited with code -1073741819 (0xc0000005) 'Access violation'.
The program '[20584] dotnet.exe: Managed (CoreCLR)' has exited with code -1 (0xffffffff).
注释field.Parent = this;
中的行public TableDef AddField(FieldDef field)
时,代码运行平稳。可能值得注意的是,即使我在此行上设置了一个断点,该程序也会终止。因为这需要2到3秒钟,所以我设法从调试器的“自动”中间窗口中的字段中读取了一些变量,它们看起来非常好。一旦我尝试访问父字段,应用程序就会死掉。
我很确定这是我自己错误解释的一些继承物。
非常感谢您的帮助。谢谢。
答案 0 :(得分:3)
似乎,您正在递归设置Parent属性,这将导致2-3秒后堆栈溢出。您可以使用私有字段来存储Parent对象,并在属性中使用它,如下所示。
private TableDef _parent;
public TableDef Parent {
get { return _parent; }
set {
this._parent = value;
ID = this._parent.Name.Replace(" ", "") + "_" + Name.Replace(" ", "");
}
}
答案 1 :(得分:1)
好的,我发现了问题。访问冲突是由于堆栈溢出而发生的,我认为这很直观(这就是为什么我在此处发布它的原因)
由于我已经实现了getter和setter的实现,所以我不能再将Property用作“字段”(仅指定{get; set;}
时就与“默认强制”相反)实现getter和setter时需要使用单独的变量:
private TableDef _parent;
public TableDef Parent {
get { return _parent; }
set {
this._parent = value;
ID = Parent.Name.Replace(" ", "") + "_" + Name.Replace(" ", "");
}
}
不应该直觉,因为编译器可以“创建”这样的代码,但是作为程序员,您不能。