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

时间:2014-12-31 19:30:57

标签: c# language-design

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

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

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

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

我认为 order 可以保证(使用静态字段)按顺序初始化,但是它也在这里应用

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();
}

结果:

A
B
C

问题

我对 reason / logic 更感兴趣,因为它受到限制。只是为了好奇。

nb没有发现任何重复。

2 个答案:

答案 0 :(得分:20)

  

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

如果您阅读C#语言规范10.11.3,则会在此处提示其基本原理。在讨论变量初始化器时:

  

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

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

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

答案 1 :(得分:5)

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

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

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