为什么C#不允许字段初始化程序使用非静态字段?

Roy*_*mir 21 c# language-design

为什么C#会允许这样:

public class MyClass
{
  static int A=1;
  static int B=A+1;
}
Run Code Online (Sandbox Code Playgroud)

但是不允许("字段初始值设定项不能引用非静态字段,方法或属性")这个

public class MyClass
{
   int A=1;
   int B=A+1;
}
Run Code Online (Sandbox Code Playgroud)

我认为它的 顺序是连续的初始化为它出现这是保证(静态字段),但它也应用在这里你可以看到:

public class MyClass
{
   int A=((Func<int>)(delegate(){ Console.WriteLine ("A"); return 1;}))();
   int B=((Func<int>)(delegate(){ Console.WriteLine ("B"); return 2;}))();
   int C=((Func<int>)(delegate(){ Console.WriteLine ("C"); return 3;}))();
}

void Main()
{
 var a = new MyClass();
}
Run Code Online (Sandbox Code Playgroud)

结果:

A
B
C
Run Code Online (Sandbox Code Playgroud)

我对它被限制的原因/逻辑更感兴趣.只是为了好奇.

nb没有发现任何重复.

Ree*_*sey 22

我对它被限制的原因/逻辑更感兴趣.只是为了好奇.

如果你阅读了C#语言规范10.11.3,它就会提到这里的基本原理.在讨论变量初始化器时:

将实例变量初始值设定项和构造函数初始值设定项视为在构造函数体之前自动插入的语句很有用.

由于这些是"在构造函数之前插入",因此它们this在有效之前执行,因此允许您(有效地this)引用其他成员会有问题.

请注意,这与static字段的工作方式一致.在这两种情况下,您可以访问静态数据,但不能访问实例数据.您收到的错误消息("字段初始值设定项不能引用非静态字段,方法或属性")直接注意到这一点.

  • 在静态构造函数运行之前(在字段初始化器中),类型也将处于无效状态.那么为什么允许访问静态成员呢?对我来说没有意义. (7认同)
  • 对我来说,本文最好地解释了它:http://www.jot.fm/issues/issue_2002_11/article4/在C#构造函数中的工作方式与Java不同 (2认同)

Tra*_*s J 6

"使用static修饰符声明一个静态成员,该成员属于该类型本身而不是特定对象." - 静态MSDN

AB被声明为静态时,它们属于该类型,MyClass并且所有实例MyClass将具有相同的AB.静态构造函数将在实例化类之前但在程序启动之后运行.此时,A已经定义,因此B可以参考它.

在另一方面,当AB不是静态的,它们只属于实例MyClass.在编译时,该字段B将尝试基于A尚未初始化的值进行初始化.MyClass编译器运行时没有实例,因此没有值A可供引用.