为什么 C# 不允许使用非静态字段的字段初始值设定项

本文关键字:字段 为什么 不允许 静态 | 更新日期: 2023-09-27 18:35:44

为什么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<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

问题

我对它受到限制的原因/逻辑更感兴趣。 只是出于好奇。

NB没有找到任何重复项。

为什么 C# 不允许使用非静态字段的字段初始值设定项

我对它受到限制的原因/逻辑更感兴趣。 只是出于好奇。

如果您阅读 C# 语言规范 10.11.3,它会提示此处的基本原理。 在讨论变量初始值设定项时:

将实例变量初始值设定项

和构造函数初始值设定项视为自动插入到构造函数主体之前的语句很有用。

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

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

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

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

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