hidebysig在MSIL方法中的目的是什么?
使用ildasm和C#程序,例如
static void Main(string[] args) { }
得到:
.method private hidebysig static void Main(string[] args) cil managed { .entrypoint // Code size 2 (0x2) .maxstack 8 IL_0000: nop IL_0001: ret } // end of method Program::Main
hidebysig构造是做什么的?
从ECMA 335分区1的第8.10.4节:
CTS提供对从基本types(隐藏)可见的名称和派生类中的布局槽共享(重写)的独立控制。 隐藏是通过将派生类中的成员标记为按名称隐藏或按名称和签名隐藏来控制的。 隐藏总是基于成员的种类执行,即派生字段名称可以隐藏基本字段名称,但不包括方法名称,属性名称或事件名称。 如果派生成员被标记为按名称隐藏,则具有相同名称的基类中相同types的成员在派生类中不可见; 如果成员被标记为隐藏,那么只有具有完全相同名称和types(对于字段)或方法签名(对于方法)的相同types的成员对派生类是隐藏的。 这两种隐藏forms之间的区别的实现完全由源语言编译器和reflection库提供; 它对VES本身没有直接的影响。
(这一点并不是很清楚,但hidebysig
意思是“隐藏名字和签名”。)
同样在分区2的第15.4.2.2节中:
hidebysig提供给工具使用,并被VES忽略。 它指定声明的方法隐藏了具有匹配方法签名的基类types的所有方法; 当省略时,该方法应该隐藏所有同名的方法,而不pipe签名是什么。
举个例子,假设你有:
public class Base { public void Bar() { } } public class Derived : Base { public void Bar(string x) { } } ... Derived d = new Derived(); d.Bar();
这是有效的,因为Bar(string)
不会隐藏Bar()
,因为C#编译器使用hidebysig
。 如果它使用“隐藏名字”的语义,你将不能够在Derived
types的引用上调用Bar()
,尽pipe你仍然可以将它转换为Base并且以这种方式调用它。
编辑:我刚刚通过编译上述代码到一个DLL,ildasming它,删除Bar()
和Bar(string)
hidebysig,再次ilasming,然后尝试从其他代码调用Bar()
Derived d = new Derived(); d.Bar(); Test.cs(6,9): error CS1501: No overload for method 'Bar' takes '0' arguments
然而:
Base d = new Derived(); d.Bar();
(没有编译问题。)
根据SKEET的回答,另外原因是Java和C#允许类的客户端调用任何名称相同的方法,包括基类的方法。 而C ++不会:如果派生类甚至定义了一个与基类中的方法具有相同名称的方法,那么客户端不能直接调用基类方法,即使它没有使用相同的参数。 所以这个特性被包含在CIL中来支持两种超载的方法。
在C ++中,您可以using
指令有效地从基类中导入一个重名的重载集合,以便它们成为该方法名称的“重载集合”的一部分。