【发布时间】:2016-02-14 00:02:42
【问题描述】:
这个问题不是关于如何初始化支持字段...
假设给定这个类:
public class Test
{
public int PropertyA { get; set; }
public int PropertyB { get; set; }
private int _propertyC;
public int PropertyC { get { return _propertyC; } set { _propertyC = value; } }
}
定义了许多属性,自动和显式实现。
让我们仔细看看PropertyA 是如何编译的(64 位调试)。 MSIL 输出是这样的:
这是非常基本的,它定义了支持字段、属性,然后是用于加载或设置支持字段的属性的 get_ 和 _set 方法。
我不明白的是(直到现在我都认为这是理所当然的),这是一个完全合法的构造函数:
public Test()
{
Debug.WriteLine($"{PropertyA.ToString()}");
Debug.WriteLine($"{_propertyC.ToString()}");
}
虽然这显然是一个编译器错误:
public Test()
{
int i;
Debug.WriteLine($"{i.ToString()}");
}
正如预期的那样,这给出了 CS0165“使用未分配的局部变量 'i'”。在为此做一些研究并挖掘ECMA Spec和Microsoft C# spec(5.0是最后一个正式文件,6.0似乎在Roslyn项目中分布松散)我找不到任何与初始化相关的东西字段。
我确实发现 this reference from VS2003 无法将类字段初始化为类型的 default 值,但它表明这是语言的一部分,而不是运行时。
所以问题是......运行时是否执行字段的初始化,或者我是否在初始化这些值的编译器中遗漏了 MSIL 中的某些内容?我假设编译器会这样做,否则我会期望在两个示例构造函数中使用相同的 CS0165。
【问题讨论】:
-
所以您基本上想了解为什么您可以调用未分配的属性但不能调用未分配的局部变量?
-
我明白为什么,但我不明白如何。初始化发生在哪里?
-
这不是在规范的 §17.4.4 中描述的吗? “字段的初始值,无论是静态字段还是实例字段,都是字段类型的默认值(第 12.2 节)。在此默认初始化发生之前,无法观察字段的值,因此,一个字段永远不会“未初始化””?如果它不在 MSIL 中,我会假设运行时会处理它。编译器只需要知道规则,即规范说它将被初始化,所以没有警告。不多不少。
-
规范的 5.3 部分涵盖了关于明确分配的部分。初始化将由运行时完成。
-
@WillemvanRumpt 感谢您在规范中找到它(从 2003 年开始移动了很多),但我明白为什么,我只是想知道在哪里实现了初始化。
标签: c# initialization