自动初始化后备字段

时间:2015-11-12 15:34:29

标签: c# initialization

这个问题关于如何初始化支持字段......

让我们说这个课程:

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。

1 个答案:

答案 0 :(得分:1)

  

运行时是否执行字段的初始化,或者我是否在初始化这些值的编译器中遗漏了MSIL中的某些内容?

规范的第5.2节和第5.3节分别讨论默认值和明确赋值。

规范引用(第5.2节):

  

初始化为默认值通常通过让内存管理器或垃圾收集器在分配使用之前将内存初始化为所有位为零来完成。因此,使用all-bits-zero表示空引用很方便。

这继续显示内存管理器和GC负责默认值初始化。