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

为什么C#会允许这样做:

public class MyClass { static int A=1; static int B=A+1; } 

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

 public class MyClass { int A=1; int B=A+1; } 

我认为这是保证(使用静态字段)顺序初始化的顺序,但它也可以在这里应用,如您所见:

 public class MyClass { int A=((Func)(delegate(){ Console.WriteLine ("A"); return 1;}))(); int B=((Func)(delegate(){ Console.WriteLine ("B"); return 2;}))(); int C=((Func)(delegate(){ Console.WriteLine ("C"); return 3;}))(); } void Main() { var a = new MyClass(); } 

结果:

 A B C 

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

nb没有发现任何重复。

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

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

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

由于这些是“在构造函数之前插入的”,因此它们在this有效之前执行,因此允许您引用其他成员(实际上是this )会有问题。

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

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

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

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