为什么在C#6.0自动属性初始化中没有`this`?

Luk*_* Vo 23 c# oop constructor automatic-properties

我有以下代码类:

public class Foo
{
    public Nested Bar { get; } = new Nested(this);

    public class Nested
    {
        public Nested(Foo foo)
        {
            foo.DoSomething();
        }
    }

    private void DoSomething()
    {

    }
}
Run Code Online (Sandbox Code Playgroud)

但是,我收到此编译错误:

关键字'this'在当前上下文中不可用

我可以通过简单地不使用自动属性初始化器来修复它,并明确地将其移动到构造函数中:

public Nested Bar { get; }

public Foo()
{
    this.Bar = new Nested(this);
}
Run Code Online (Sandbox Code Playgroud)

为什么会这样?是不是Auto-Property Initializer实际上转换为IL中的构造函数代码?

Mar*_*ell 41

简单地说:你不能this在初始化器中使用.这个想法是为了防止一个不完整的对象逃脱 - Nested(this)可以对你的对象做任何事情,导致非常混乱和难以理解的错误.请记住,初始化程序您添加的任何构造函数之前执行.对于字段初始化器,同样的事情也是如此,完全相同:

private Nested _field = new Nested(this);
Run Code Online (Sandbox Code Playgroud)

本质上,初始化程序旨在执行简单的初始化 - 修复98%的问题.涉及的任何事情this都比较复杂,你需要编写自己的构造函数 - 并承担任何时间问题的责任:)

  • @DatVM本质上是**在IL级别发生的事情; 我非常刻意地说"你添加的任何构造函数" - 所以:*如果你添加*一个构造函数,它就没有时间做任何事了.还有初始化顺序的问题:哪些初始化程序已经运行了?如果你没有构造函数的显式时序,那么获得正确就变得非常棘手.语言作者不喜欢会增加细微复杂性的东西,所以:这种用法被迫使用构造函数 (4认同)

Jon*_*eet 16

为什么会这样?是不是Auto-Property Initializer实际上转换为IL中的构造函数代码?

出于同样的原因,自动实现的属性初始值设定项的规则与字段初始值设定项的规则相同.请注意,属性初始值设定项基类体之前执行,就像字段初始值设定项一样 - 因此您仍然处于"有点未初始化"对象的上下文中; 比在构造函数体中更多.

所以你应该想象该属性正在转换为:

private readonly Nested bar = new Nested(this); // Invalid

public Nested Bar
{
    get { return bar; }
}
Run Code Online (Sandbox Code Playgroud)

简而言之,这种限制是为了阻止你陷入麻烦.如果this在初始化属性时需要引用,只需在构造函数中手动执行,如第二个示例所示.(根据我的经验,这是相对罕见的.)