使用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提供对从基类型(隐藏)可见的名称和派生类中的布局槽共享(覆盖)的独立控制.通过将派生类中的成员标记为按名称隐藏或按名称和签名隐藏来控制隐藏.隐藏始终基于成员的类型执行,即派生的字段名称可以隐藏基本字段名称,但不能隐藏方法名称,属性名称或事件名称.如果派生成员按名称标记为hide,则基类中具有相同名称的同类成员在派生类中不可见; 如果成员通过名称和签名标记为隐藏,则只有具有完全相同名称和类型(对于字段)或方法签名(对于方法)的相同类型的成员才会从派生类中隐藏.这两种隐藏形式之间的区别的实现完全由源语言编译器和反射库提供; 它对VES本身没有直接影响.
(这不是立即清楚,但hidebysig
意味着"隐藏名称和签名".)
同样在分区2的第15.4.2.2节中:
hidebysig是为工具的使用而提供的,并被VES忽略.它指定声明的方法隐藏具有匹配方法签名的基类类型的所有方法; 省略时,该方法应隐藏所有同名方法,无论签名如何.
举个例子,假设你有:
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
.如果它使用"隐藏名称"语义,你将无法Bar()
在类型的引用上调用Derived
,尽管你仍然可以将它转换为Base并以这种方式调用它.
编辑:我刚刚通过编译上面的代码到一个DLL,它ildasming,消除尝试这样hidebysig
的Bar()
和Bar(string)
,再次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();
(没有编译问题.)
根据THE SKEET的回答,另外的原因是Java和C#允许类的客户端调用任何具有相同名称的方法,包括来自基类的方法.而C++没有:如果派生类甚至定义了与基类中的方法同名的单个方法,那么客户端也不能直接调用基类方法,即使它不采用相同的参数.因此,该功能包含在CIL中以支持两种重载方法.
在C++中,您可以使用using
指令从基类中有效地导入一组命名的重载,以便它们成为该方法名称的"重载集"的一部分.