Auto-属性 初始化程序引用实例成员

Auto-property with initializer referencing instance member

这是工作代码

public class SomeViewModel
{
    public DelegateCommand CommandA { get; }
    public DelegateCommand CommandB { get; }

    public bool SomeProperty { get; set; }        

    // stupid constructor
    public SomeViewModel()
    {
        CommandA = new DelegateCommand(OnCommandA);
        CommandB = new DelegateCommand(o => SomeProperty = true;);
    }
    void OnCommandA(object obj) { ... }
}

而这个不是

public class SomeViewModel
{
    public DelegateCommand CommandA { get; } = new DelegateCommand(OnCommandA); // error
    public DelegateCommand CommandB { get; } = new DelegateCommand(o => SomeProperty = true;); // error

    public bool SomeProperty { get; set; }        

    void OnCommandA(object obj) { ... }
}

错误是

Error CS0236 A field initializer cannot reference the non-static field, method, or property

我的问题是:为什么?为什么某些东西应该是 static?这应该是一个很酷的功能。

这里真的没有什么新鲜事。忘记自动实现的属性 - 您根本无法在字段初始值设定项中引用 this。 (让我们面对现实吧,您正在尝试初始化引擎盖下的一个字段 - 只是一个仅通过 属性 公开的字段。)

所以这个一直无效:

class Foo
{
    int x = 10;
    int y = x; // Nope, compile-time error
    int z = DoSomething(); // Nope...

    int DoSomething() { ... }
}

通常,这可以避免:

  • 依赖初始化顺序,这可能导致代码脆弱
  • 在基本 class 初始化程序执行之前调用方法

我同意,对于方法组转换,这是一个 不必要的痛苦 - 但语言更简单,只有一个规则。

如您所见,您可以轻松地将代码放入构造函数中 - 所以我会这样做。 (嘿,至少我们现在 可以从构造函数初始化的只读自动实现的属性...)

重要的是要了解编译器错误消息并没有真正告诉您任何东西应该是静态的——它只是告诉您什么不能做。解决方案取决于您的情况 - 在这种情况下,正确的解决方案几乎肯定是将初始化放在构造函数中。