让我们考虑这个课程:
class ABClass
{
object a;
object b;
object[] ab = new[] {a, b};
}
这不编译:
A field initializer cannot reference the non-static field, method, or property 'TestConsole.ABClass.a'
A field initializer cannot reference the non-static field, method, or property 'TestConsole.ABClass.b'
但是,R#建议成功修复编译:
class ABClass
{
object a;
object b;
object[] ab;
public ABClass()
{
ab = new[] {a, b};
}
}
为什么数组初始化似乎发生在静态上下文中?
跟进:在C#6中有auto-properties with initializers功能。它与我的问题有什么关系?
答案 0 :(得分:6)
你问过:**Why** does the array initialization **seem to happen** in a static context?
。
不要指向你的语言规范(简单明确地说"你不能这样做,期间"),而不是考虑原因。
它发生在静态上下文中,因为否则,它将使用半构造的对象实例。字段a, b
可能是,也可能未初始化。它们可以从构造函数,基本构造函数或派生构造函数,从基础/派生方法访问,这些方法可以通过虚拟/覆盖从此构造函数或基础构造函数等调用。
如果字段'允许初始化程序读取/引用其他实例字段和/或调用实例方法,编译器无法猜测字段初始化的正确顺序。
此外,请注意字段初始化过程在构造函数之前执行。允许字段访问实例字段/ props / methods意味着可以在调用构造函数(和基础构造函数)之前调用这些方法,这会导致许多奇怪和违反直觉的影响。
因此,该语言的设计是为了防止它。初始化器被简单地设计/强制在静态上下文中执行,因此您不会想要依赖半构造的对象实例功能,因此您不会过多地混淆代码。这样,你就不会意外忘记危险。你仍然可以在构造函数中完成所有这些,但是你总是知道"它的构造函数"自然你会更加谨慎。当然,你仍然可以通过调用ctor中的虚拟方法来自己动手,但是,跟踪和调试要容易得多,就像在构造函数的代码中至少执行顺序强>线是显而易见的,而初始化则可能不是这样。
答案 1 :(得分:1)
原因是因为Specs这么说:
字段初始值设定项不能引用非静态字段,方法或 属性
您的字段a
和b
是非静态的。您无法在对象初始值设定项中访问它们。这就是你需要一个构造函数的原因。
对于C#6自动属性初始化器:
这与您的代码无关,您没有任何自动实现的属性。
答案 2 :(得分:0)
来自MSDN"实例字段的变量初始化程序无法引用正在创建的实例。"
这是源自http://msdn.microsoft.com/en-us/library/aa645759(v=vs.71).aspx
的链接进一步阅读实例构造函数:http://msdn.microsoft.com/en-us/library/aa645602(v=vs.71).aspx