为什么 `this` 在 C# 6.0 Auto-属性 Initialization 中不可用?

Why is `this` not available in C# 6.0 Auto-Property Initialization?

我有以下代码class:

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

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

    private void DoSomething()
    {

    }
}

但是,我得到这个编译错误:

Keyword 'this' is not available in the current context

我可以通过简单地不使用 Auto-属性 初始化器来修复它,而是显式地将它移动到构造函数中:

public Nested Bar { get; }

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

为什么会这样? Auto-属性 Initializer 实际上不是在 IL 中翻译成构造函数代码吗?

Why is it so? Isn't Auto-Property Initializer actually translated into constructor code in IL?

出于同样的原因,自动实现的 属性 初始化器的规则与字段初始化器的规则相同。请注意,属性 初始化器在 before 基础 class 主体中执行,就像字段初始化器一样 - 所以您仍在 "somewhat uninitialized" 对象的上下文中;比在构造函数主体期间更重要。

所以你应该想象 属性 被转换成这样:

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

public Nested Bar
{
    get { return bar; }
}

简而言之,这个限制是为了让你不要惹上麻烦。如果在初始化 属性 时需要引用 this,只需在构造函数中手动执行,如第二个示例所示。 (根据我的经验,这种情况比较少见。)

简单地说:你不能在初始化器中使用this。这个想法是为了防止不完整的对象转义 - Nested(this) 可以对你的对象做 任何事情,从而导致非常混乱和难以理解的错误。请记住,初始化程序会在您添加的任何构造函数之前执行。同样的事情对于字段初始值设定项也以完全相同的方式失败:

private Nested _field = new Nested(this);

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