8

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

// "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其视为一种方法。

让方法成为属性的魔法酱是什么?

4

2 回答 2

7

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

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

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

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

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

于 2012-10-26T13:15:01.777 回答
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将两种方法粘合在一起的成员。

于 2012-10-26T13:16:00.090 回答