使用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构造有什么作用?
答案 0 :(得分:148)
来自ECMA 335,分区1的第8.10.4节:
CTS提供独立控制 在两个可见的名称上 从基类型(隐藏)和 在派生中共享布局槽 上课(重写)。隐藏是 通过标记成员来控制 派生类可以按名称隐藏 或通过名称和签名隐藏。藏 总是根据种类进行 成员,即派生字段 名称可以隐藏基本字段名称,但是 不是方法名,属性名或 事件名称。如果派生成员是 按名称标记隐藏,然后是成员 与基类中的同类 在...中看不到相同的名字 派生类;如果成员被标记 隐藏名称和签名然后只有一个 完全相同的成员 相同的名称和类型(对于字段)或 方法签名(方法)是 隐藏在派生类中。 执行区别 这两种隐藏形式之间是 完全由源语言提供 编译器和反射库; 它对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()
的{{1}},再次将其重新填充,然后尝试调用来自其他代码的Bar(string)
:
Bar()
然而:
Derived d = new Derived();
d.Bar();
Test.cs(6,9): error CS1501: No overload for method 'Bar' takes '0' arguments
(没有编译问题。)
答案 1 :(得分:14)
根据THE SKEET的回答,另外原因是Java和C#允许类的客户端调用任何具有相同名称的方法,包括来自基类的方法。而C ++却没有:如果派生类甚至定义了与基类中的方法同名的单个方法,那么客户端也不能直接调用基类方法,即使它不采用相同的参数。因此,该功能包含在CIL中,以支持两种重载方法。
在C ++中,您可以使用using
指令从基类中有效地导入一组命名的重载,以便它们成为该方法名称的“重载集”的一部分。
答案 2 :(得分:0)
使用C#
new
修饰符声明派生类中的成员时 或Visual BasicShadows
修饰符,它可以隐藏相同的成员 基类中的名称。 C#通过签名隐藏基类成员。那 是,如果基类成员有多个重载,那么唯一的一个 隐藏的是具有相同签名的那个。相比之下, Visual Basic隐藏所有基类重载。因此,IsHideBySig 对使用Visual Basicfalse
声明的成员返回Shadows
修饰符,以及使用C#true
修饰符声明的成员上的new
。