Od ECMA 335 , sekcja 8.10.4 partycji 1:
CTS zapewnia niezależną kontrolę zarówno nad nazwami, które są widoczne z typu podstawowego (ukrywanie), jak i współdzieleniem szczelin układu w klasie pochodnej (nadpisywanie). Ukrywanie jest kontrolowane przez oznaczenie elementu członkowskiego w klasie pochodnej jako ukrycia według nazwy lub ukrycia według nazwy i podpisu. Ukrywanie jest zawsze wykonywane na podstawie rodzaju elementu członkowskiego, co oznacza, że nazwy pól pochodnych mogą ukrywać nazwy pól bazowych, ale nie nazwy metod, nazwy właściwości lub nazwy zdarzeń. Jeśli element członkowski pochodny jest oznaczony jako ukryj według nazwy, elementy członkowskie tego samego rodzaju w klasie bazowej o tej samej nazwie nie są widoczne w klasie pochodnej; jeśli element członkowski jest oznaczony jako ukryj według nazwy i podpisu, wówczas tylko element członkowski tego samego rodzaju o dokładnie tej samej nazwie i typie (dla pól) lub sygnaturze metody (dla metod) jest ukryty w klasie pochodnej. Implementacja rozróżnienia między tymi dwoma formami ukrywania jest całkowicie zapewniana przez kompilatory języka źródłowego i bibliotekę refleksji; nie ma bezpośredniego wpływu na sam VES.
(Nie jest to od razu jasne, ale hidebysig
oznacza „ukryj według nazwy i podpisu”).
Również w sekcji 15.4.2.2 przegrody 2:
hidebysig jest dostarczany do użytku z narzędziami i jest ignorowany przez VES. Określa, że zadeklarowana metoda ukrywa wszystkie metody typów klas bazowych, które mają pasującą sygnaturę metody; jeśli zostanie pominięty, metoda powinna ukryć wszystkie metody o tej samej nazwie, niezależnie od podpisu.
Na przykład załóżmy, że masz:
public class Base
{
public void Bar()
{
}
}
public class Derived : Base
{
public void Bar(string x)
{
}
}
...
Derived d = new Derived();
d.Bar();
To jest poprawne, ponieważ Bar(string)
się nie ukrywa Bar()
, ponieważ kompilator C # używa hidebysig
. Gdyby używał semantyki „ukryj według nazwy”, nie byłbyś w stanie Bar()
w ogóle wywołać referencji typu Derived
, chociaż nadal możesz rzutować je na Base i nazwać w ten sposób.
EDIT: Właśnie próbowałem kompilując powyższy kod do pliku DLL, ildasming go, usuwając hidebysig
na Bar()
i Bar(string)
, ilasming go ponownie, a następnie próby wywołania Bar()
z innego kodu:
Derived d = new Derived();
d.Bar();
Test.cs(6,9): error CS1501: No overload for method 'Bar' takes '0' arguments
Jednak:
Base d = new Derived();
d.Bar();
(Brak problemów z kompilacją).
Shadows
iOverloads
w VB.NET.Zgodnie z odpowiedzią THE SKEET, dodatkowo jest to spowodowane tym, że Java i C # pozwalają klientowi klasy na wywoływanie dowolnych metod o tej samej nazwie, w tym z klas bazowych. Podczas gdy C ++ nie: jeśli klasa pochodna definiuje nawet jedną metodę o takiej samej nazwie jak metoda w klasie bazowej, to klient nie może bezpośrednio wywołać metody klasy bazowej, nawet jeśli nie przyjmuje ona tych samych argumentów. Tak więc funkcja została uwzględniona w CIL, aby obsługiwać oba podejścia do przeciążania.
W C ++ można efektywnie zaimportować jeden nazwany zestaw przeciążeń z klasy bazowej za pomocą
using
dyrektywy, aby stały się one częścią „zestawu przeciążeń” dla tej nazwy metody.źródło
Według Microsoft Docs
źródło