Яка мета приховування в методі MSIL?


92

Використання 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?

Відповіді:


156

З 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 і назвати так.

РЕДАГУВАТИ: Я щойно спробував це, скомпілювавши наведений вище код у DLL, ілдасміруючи його, видаливши hidebysigдля Bar()і Bar(string), знову іламуючи його, потім спробувавши зателефонувати 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();

(Немає проблем із компіляцією.)


4
В цілому , це різниця між Shadowsі Overloadsв VB.NET.
Mark Hurd

16

Відповідно до відповіді THE SKEET, крім того, причиною цього є те, що Java і C # дозволяють клієнту класу викликати будь-які методи з однаковим іменем, включаючи методи базових класів. Тоді як C ++ ні: якщо похідний клас визначає навіть один метод з тим самим іменем, що і метод у базовому класі, то клієнт не може безпосередньо викликати метод базового класу, навіть якщо він не приймає однакові аргументи. Тож ця функція була включена в CIL для підтримки обох підходів до перевантаження.

У C ++ ви можете ефективно імпортувати один іменований набір перевантажень з базового класу за допомогою usingдирективи, щоб вони стали частиною "набору перевантажень" для цього імені методу.


1

Відповідно до Microsoft Docs

Коли член у похідному класі оголошений із newмодифікатором C # або модифікатором Visual Basic Shadows, він може приховати член з тим самим іменем у базовому класі. C # приховує членів базового класу підписом. Тобто, якщо член базового класу має кілька перевантажень, приховується єдиний, що має ідентичний підпис. На відміну від цього, Visual Basic приховує всі перевантаження базового класу. Таким чином, IsHideBySig повертається falseдо члена, оголошеного за допомогою Shadows модифікатора Visual Basic , і trueдо члена, оголошеного за допомогою newмодифікатора C # .

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.