从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()
type 的引用Derived
,尽管您仍然可以将其强制转换为 Base 并以这种方式调用它。
编辑:我刚刚尝试通过将上述代码编译为 DLL,对其进行 ildasming,删除hidebysig
for Bar()
and 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();
(没有编译问题。)