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

Dan*_*ite 8 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();
   }
}
Run Code Online (Sandbox Code Playgroud)

现在我很好奇,我把一个带有类似签名的方法Class1看作是访问者的标准约定.

// "Hacked" example
class Class1 {
   public bool get_Boolean() { return true; }
}
Run Code Online (Sandbox Code Playgroud)

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

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

sta*_*ica 7

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

在方法的情况下,发出描述方法的名称,签名等的元数据.

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

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

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


dtb*_*dtb 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 
{
    ...
}
Run Code Online (Sandbox Code Playgroud)

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