Из ECMA 335 , раздел 8.10.4 раздела 1:
CTS обеспечивает независимый контроль как над именами, которые видны из базового типа (скрытие), так и над совместным использованием слотов макета в производном классе (переопределение). Скрытие контролируется пометкой члена в производном классе как скрытого по имени или как скрытого по имени и подписи. Скрытие всегда выполняется в зависимости от типа члена, то есть производные имена полей могут скрывать имена базовых полей, но не имена методов, имена свойств или имена событий. Если производный член помечен как скрытие по имени, то члены того же типа в базовом классе с тем же именем не видны в производном классе; если член помечен как скрытый по имени и сигнатуре, то только член того же типа с точно таким же именем и типом (для полей) или сигнатурой метода (для методов) скрывается от производного класса. Реализация различия между этими двумя формами сокрытия полностью обеспечивается компиляторами исходного языка и библиотекой отражения; он не имеет прямого воздействия на сам VES.
(Это не сразу понятно, но hidebysig
означает «скрыть по имени и подписи».)
Также в разделе 15.4.2.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 и называть ее таким образом.
EDIT: Я просто попытался это путем составления вышеуказанного кода в 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();
(Нет проблем с компиляцией.)
Shadows
иOverloads
в VB.NET.Согласно ответу THE SKEET, кроме того, причина в том, что Java и C # позволяют клиенту класса вызывать любые методы с тем же именем, в том числе из базовых классов. В то время как C ++ этого не делает: если производный класс определяет даже один метод с тем же именем, что и метод в базовом классе, то клиент не может напрямую вызвать метод базового класса, даже если он не принимает те же аргументы. Таким образом, эта функция была включена в CIL для поддержки обоих подходов к перегрузке.
В C ++ можно эффективно импортировать один именованный набор перегрузок из базового класса с помощью
using
директивы, чтобы они стали частью «набора перегрузок» для этого имени метода.источник
Согласно Microsoft Docs
источник