访问对象字段时发生访问冲突异常

wol*_*uli 6 c# linq access-violation visual-studio

在我的 .Net Core 2.0、ASP.Net React 项目中使用 Linq 时,我遇到了一个非常奇怪的行为:

当访问在 Linq“Select”选择器内实例化的对象的字段时,它会抛出“访问冲突异常”

重现步骤(希望如此):

  • 视觉工作室 2017,15.7.4
  • 创建新的 ASP.Net Core 2.0 项目
  • 选择“反应”模板
  • 更改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 秒,我设法从调试器的“自动”中间窗口中的字段读取一些变量,它们看起来非常好。一旦我尝试访问父字段,应用程序就会终止。

我很确定这是我自己错误解释的一些继承的东西。

任何帮助深表感谢。谢谢。

wol*_*uli 8

好吧,我发现问题了。访问冲突是由于堆栈溢出而发生的,我认为这是违反直觉的(这就是我将其发布在这里的原因)

当属性将值设置为其自身时如何发生堆栈溢出异常

由于我有 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)

恕我直言,这是违反直觉的,因为编译器可以“创建”这样的代码,但作为程序员你不能。