2015-11-12 57 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照顧默認值初始化。