2015-11-12 55 views
2

这个问题有关如何初始化支持字段的自动初始化...支持字段

比方说给这个类:

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输出是这样的:

 
.field private int32 'k__BackingField' 
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (01 00 00 00) 
.custom instance void [mscorlib]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggerBrowsableState) = (01 00 00 00 00 00 00 00) 

.property instance int32 PropertyA() 
{ 
    .get instance int32 TestCode.Test::get_PropertyA() 
    .set instance void TestCode.Test::set_PropertyA(int32) 
} // end of property Test::PropertyA 

.method public hidebysig specialname instance int32 
     get_PropertyA() cil managed 
{ 
    .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (01 00 00 00) 
    // Code size  7 (0x7) 
    .maxstack 8 
    IL_0000: ldarg.0 
    IL_0001: ldfld  int32 TestCode.Test::'k__BackingField' 
    IL_0006: ret 
} // end of method Test::get_PropertyA 

.method public hidebysig specialname instance void 
     set_PropertyA(int32 'value') cil managed 
{ 
    .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (01 00 00 00) 
    // Code size  8 (0x8) 
    .maxstack 8 
    IL_0000: ldarg.0 
    IL_0001: ldarg.1 
    IL_0002: stfld  int32 TestCode.Test::'k__BackingField' 
    IL_0007: ret 
} // end of method Test::set_PropertyA 

这是非常基本的,它定义了支持字段,属性,然后将get__set方法为该属性,负载或设置支持字段。

我没有得到什么(我认为是理所当然的,直至现在),是,这是一个完全合法的构造函数:

public Test() 
{ 
    Debug.WriteLine($"{PropertyA.ToString()}"); 
    Debug.WriteLine($"{_propertyC.ToString()}"); 
} 

虽然这显然是一个编译器错误:

public Test() 
{ 
    int i; 
    Debug.WriteLine($"{i.ToString()}"); 
} 

其中,如预期的那样,给CS0165“使用未分配的本地变量'i'”。在为此进行一些研究并挖掘ECMA SpecMicrosoft C# spec(5.0是最后一份正式文档,6.0似乎松散地分布在Roslyn项目中),并且我找不到与字段初始化相关的任何内容。

我确实发现this reference from VS2003逃避到类字段被初始化为default类型的值,但它表明这是语言的一部分,而不是运行时。

所以问题是......运行时是否执行字段的初始化,或者我是否正在初始化这些值的编译器中丢失MSIL中的某些内容?我假设编译器这样做,否则我会期望在这两个示例构造函数中相同的CS0165。

+0

所以你基本上想知道为什么你可以调用一个未分配的属性,但不是一个未分配的本地变量? –

+0

我明白*为什么*但我不明白*如何*。初始化发生在哪里? –

+0

规范的第17.4.4节中没有对此进行描述吗? “字段的初始值,无论是静态字段还是实例字段,都是字段类型的缺省值(第12.2节)。在默认初始化发生之前,无法观察字段的值,并且一个字段从来没有“未初始化”?如果它不在MSIL中,我会假定运行时会处理它。编译器只需要知道规则,即规范说它将被初始化,所以没有警告。没有什么比这更少。 –

回答

1

Does the runtime perform the initialization of the fields, or am I missing something in the MSIL from the compiler that is initializing these values?

说明书第5.2部分和第5.3部分分别讨论了默认值和明确赋值。

从规范(第5.2节)引述:

Initialization to default values is typically done by having the memory manager or garbage collector initialize memory to all-bits-zero before it is allocated for use. For this reason, it is convenient to use all-bits-zero to represent the null reference.

这正好显示内存管理和GC照顾默认值初始化。