wol*_*uli 6 c# linq access-violation visual-studio
在我的 .Net Core 2.0、ASP.Net React 项目中使用 Linq 时,我遇到了一个非常奇怪的行为:
当访问在 Linq“Select”选择器内实例化的对象的字段时,它会抛出“访问冲突异常”
重现步骤(希望如此):
更改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) +
"]";
}
Run Code Online (Sandbox Code Playgroud)具有以下类别:
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;
}
}
Run Code Online (Sandbox Code Playgroud)当运行代码并单击“获取数据”链接时,应用程序完全终止(至少在我的情况下),甚至在 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).
Run Code Online (Sandbox Code Playgroud)
当注释代码field.Parent = this;中的行时,运行顺利。public TableDef AddField(FieldDef field)值得注意的是,即使我在这一行放置了断点,程序也会死掉。由于这需要 2 或 3 秒,我设法从调试器的“自动”中间窗口中的字段读取一些变量,它们看起来非常好。一旦我尝试访问父字段,应用程序就会终止。
我很确定这是我自己错误解释的一些继承的东西。
任何帮助深表感谢。谢谢。
好吧,我发现问题了。访问冲突是由于堆栈溢出而发生的,我认为这是违反直觉的(这就是我将其发布在这里的原因)
由于我有 getter 和 setter 的实现,因此我不能再将属性用作“字段”(与仅指定 { get; set; } 时的“默认实现”相反)
在实现 getter 和 setter 时需要使用单独的变量:
private TableDef _parent;
public TableDef Parent {
get { return _parent; }
set {
this._parent = value;
ID = Parent.Name.Replace(" ", "") + "_" + Name.Replace(" ", "");
}
}
Run Code Online (Sandbox Code Playgroud)
恕我直言,这是违反直觉的,因为编译器可以“创建”这样的代码,但作为程序员你不能。