使属性与CLR一起工作的神奇之处是什么?

时间:2012-10-26 13:10:19

标签: c# clr syntactic-sugar

我注意到当我反映到一个程序集时,对属性访问器的调用有时看起来像方法

// "Reflected" example
class Class1 {
   public bool Boolean { get; set;}
}

class Class2 {
   public Class2() {
       var class1 = new Class1();
       var boolean = class1.get_Boolean();
   }
}

现在我很好奇,我在Class1中添加了一个类似签名的方法,看起来像是访问者的标准约定。

// "Hacked" example
class Class1 {
   public bool get_Boolean() { return true; }
}

不知何故,C#编译器仍然将get_Boolean视为一种方法。

获得方法成为财产的神奇之处是什么?

2 个答案:

答案 0 :(得分:7)

.NET程序集不仅包含代码,还包含描述代码的元数据

对于方法,会发出描述方法名称,签名等的元数据

对于属性X,它被编译为一堆访问器方法(get_X和/或set_X),并且对于每个方法,通常的方法元数据发出。然后,发出额外的元数据,指定所有这些访问器方法实际上属于一个逻辑实体(属性)。

现在,回到您的示例:如果使用C#定义名为get_Boolean的方法,则C#编译器将仅发出方法元数据,但不会发出其他属性元数据。本质上,编译器可以选择要发出的元数据。由于您没有将C#语法用于属性,而是使用方法声明语法,因此C#编译器将为其生成元数据。

元数据在ECMA 335 standard中有详细描述,它描述了CLI(.NET平台)。有关属性元数据如何工作的说明,请参阅第241页的第II.22.34页

答案 1 :(得分:7)

如果你看看IL,你会发现这样的事情:

.property instance string Source()
{
    .get instance string System.Exception::get_Source()
    .set instance void System.Exception::set_Source(string)
}

.method public hidebysig specialname newslot virtual 
    instance string get_Source () cil managed 
{
    ...
}

.method public hidebysig specialname newslot virtual 
    instance void set_Source (
        string 'value'
    ) cil managed 
{
    ...
}

所以'魔术'是.property成员,它将两种方法粘合在一起。