访问对象

时间:2018-07-09 20:41:36

标签: c# visual-studio linq access-violation

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

访问在Linq“选择”选择器中实例化的对象的字段时,它将引发“访问冲突异常”

希望复制的步骤:

  • Visual Studio 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) +
            "]";
    }
    
  • 具有以下类别:

    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秒钟,所以我设法从调试器的“自动”中间窗口中的字段中读取了一些变量,它们看起来非常好。一旦我尝试访问父字段,应用程序就会死掉。

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

非常感谢您的帮助。谢谢。

2 个答案:

答案 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)

好的,我发现了问题。访问冲突是由于堆栈溢出而发生的,我认为这很直观(这就是为什么我在此处发布它的原因)

this from my employer

由于我已经实现了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(" ", "");
    }
} 

不应该直觉,因为编译器可以“创建”这样的代码,但是作为程序员,您不能。