C# 具有引用实例成员的初始值设定项的Auto属性

C# 具有引用实例成员的初始值设定项的Auto属性,c#,properties,initializer,c#-6.0,C#,Properties,Initializer,C# 6.0,这是工作代码 public class SomeViewModel { public DelegateCommand CommandA { get; } public DelegateCommand CommandB { get; } public bool SomeProperty { get; set; } // stupid constructor public SomeViewModel() { Comm

这是工作代码

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) { ... }
}
错误是

错误CS0236字段初始值设定项无法引用非静态字段、方法或属性


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

这里真的没有什么新东西。忘记自动实现的属性-您不能在字段初始值设定项中引用此。(让我们面对现实,您正试图初始化引擎盖下的一个字段——只是一个仅通过属性公开的字段。)

所以这一直是无效的:

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

    int DoSomething() { ... }
}
通常,这可以避免:

  • 依赖于初始化顺序,这可能导致脆弱的代码
  • 在基类初始值设定项执行之前调用方法
我同意,对于方法组转换来说,这是一个不必要的痛苦-但是语言更简单,只有一条规则

正如您所看到的,您可以很容易地将代码放入构造函数中—所以我就这样做了。(嘿,至少我们现在有只读的自动实现的属性,可以从构造函数初始化…)


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

Jon,如果两个成员都是静态的,这是允许的。显然,这也依赖于初始化的顺序,但为什么允许这样做呢?(我一直在努力寻找答案)@SriramSakthivel:嗯,在这种情况下,事情至少简单一点,因为不涉及继承。我认为这主要是因为安全性和不便性之间的权衡是不同的——在这种情况下总是要编写一个静态构造函数是非常不方便的,但是在某些情况下,您通常都有一个构造函数,并且不太可能基于另一个字段初始化一个字段。