Какова цель hidebysig в методе MSIL?
используя 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?
3 ответов:
С 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, хотя вы все еще мог бросить его на базу и назвать его так.EDIT: я только что попробовал это, скомпилировав приведенный выше код в DLL, ildasming его, удаляя
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();(нет проблем с компиляцией.)
согласно ответу скита, кроме того, причина этого заключается в том, что Java и C# позволяют клиенту класса вызывать любые методы с тем же именем, в том числе из базовых классов. Если производный класс определяет даже один метод с тем же именем, что и метод в базовом классе, то клиент не может напрямую вызвать метод базового класса, даже если он не принимает те же аргументы. Таким образом, эта функция была включена в CIL для поддержки обоих подходов к перегрузка.
в C++ вы можете эффективно импортировать один именованный набор перегрузок из базового класса с помощью
usingдиректива, чтобы они стали частью "перегрузочного набора" для этого имени метода.
по данным Microsoft Docs
когда член в производном классе объявляется с C#
newмодификатор или Visual BasicShadowsмодификатор, он может скрыть член того же имя в базовом классе. C# скрывает членов базового класса по подписи. Что если член базового класса имеет несколько перегрузок, то только одна из них скрыт тот, который имеет идентичную подпись. По контрасту, Visual Basic скрывает все перегрузки базового класса. Таким образом, IsHideBySig возвращаетfalseна члене, объявленном с помощью Visual BasicShadowsмодификатор, иtrueна члене, объявленном с помощью C#newмодификатор.
Comments