Определение сигнатуры метода?
Каково правильное определение сигнатуры метода (или сигнатуры метода)?
На Google я нахожу различные определения:
Это комбинация имени метода и списка параметров
Это значит method signature = method name + argument list
? Тогда я не вижу разницы между "методом" и "сигнатурой метода".
Если у меня есть метод:
public void Foo(int x, int y) { ... }
Подпись моего метода будет одной из следующих или нет?
- Foo
- Foo (int, int)
- Foo (int x, int y)
- Фу (34, 78)
Как мне ответить, если кто-то спросит меня, что является сигнатурой метода?
7 ответов
Здесь есть ряд правильных ответов, которые определяют сигнатуру метода как имя метода, общую арность, формальную форму арности и типы и виды формальных параметров, но не тип возвращаемого значения или модификатор "params".
Хотя это правильно, здесь есть некоторые тонкости. То, как язык C# определяет сигнатуру метода, отличается от того, как CLR определяет сигнатуру метода, и это может привести к некоторым интересным проблемам при взаимодействии между C# и другими языками.
Для CLR сигнатура метода состоит из имени метода, общей арности, арности формальных параметров, типов и видов формальных параметров и возвращаемого типа. Итак, есть первое отличие; CLR считает тип возвращаемого значения.
CLR также не считает "out" и "ref" различными типами формальных параметров; C# делает.
CLR также имеет интересную функцию, называемую "необязательные и обязательные модификаторы типов", обычно называемые "modopts" и "modreqs". Можно пометить тип в сигнатуре метода другим типом, который сообщает вам о "основном" типе. Например, в C++ это две разные подписи:
void M(C const & x);
void M(C & x);
Обе подписи определяют метод M, который принимает параметр типа "ссылка на C". Но поскольку первая ссылка является константной, а вторая - нет, язык C++ считает, что это разные сигнатуры. CLR реализует это, позволяя компилятору C++/CIL выдавать modopt для специального типа "this is const" в типе формального параметра.
Нет способа прочитать или установить мод в C#, но компилятор C#, тем не менее, знает о них и в некотором роде соблюдает их. Например, если у вас был публичный виртуальный метод, объявленный в C++/CIL, например:
void V(C const * x)
и вы переопределяете, что в производном классе, написанном на C#, компилятор C# не обеспечит вам правильность const; компилятор C# понятия не имеет, что означает const modopt. Но компилятор C# гарантирует, что переопределяющий метод будет передан в метаданные при установленном modopt. Это необходимо, потому что CLR требует подписи переопределенных и переопределенных методов для сопоставления; компилятор должен подчиняться правилам CLR для сопоставления подписи, а не правилам C#.
Из MSDN:
Сигнатура метода состоит из имени метода, а также типа и вида (значения, ссылки или вывода) каждого из его формальных параметров, рассматриваемых в порядке слева направо. Сигнатура метода специально не включает тип возвращаемого значения и не включает модификатор params, который может быть указан для самого правого параметра.
Важной частью здесь является то, что тип возвращаемого значения метода не принадлежит его сигнатуре. Таким образом, вы не можете перегружать методы, которые отличаются только типом возвращаемого значения!
Подпись метода - это набор атрибутов метода, который компилятор может использовать для идентификации метода.
Атрибуты: имя метода, количество параметров, тип параметра и порядок параметров.
Пример различных сигнатур методов:
Foo()
Foo(int)
Foo(String)
Foo(int, string)
Foo(string, int)
Все эти методы различны, и когда вы вызываете их в коде, компилятор может определить, какой метод вы намерены выполнить, используя сигнатуру метода.
Не забывайте о масштабах методов модульного программирования...
Подпись метода включает следующие элементы:
- Название метода.
- Количество параметров.
- Типы данных и порядок параметров.
Примечание. Тип возвращаемого значения не является частью подписи.
В приведенном выше примере сигнатурой метода является Foo(int x, int y). Это важно знать, потому что в языках, которые допускают перегрузку методов (таких как C# и Java), имя метода будет одинаковым, но подпись должна отличаться.
Раздел 3.6 Спецификации языка C# (v 4.0) дает наиболее точный ответ относительно сигнатур методов:
Сигнатура метода состоит из имени метода, количества параметров типа, а также типа и вида (значения, ссылки или вывода) каждого из его формальных параметров, рассматриваемых в порядке слева направо. Для этих целей любой параметр типа метода, который встречается в типе формального параметра, идентифицируется не по имени, а по порядковой позиции в списке аргументов типа метода. Сигнатура метода, в частности, не включает тип возвращаемого значения, модификатор params, который может быть указан для самого правого параметра, или необязательные ограничения параметров типа.
Статья MSDN "Методы (Руководство по программированию в C#)"
говорит:
Методы объявляются в классе или структуре путем указания уровня доступа, такого как открытый или закрытый, необязательных модификаторов, таких как абстрактный или закрытый, возвращаемого значения, имени метода и любых параметров метода. Эти части вместе являются сигнатурой метода.
И далее, что я не видел среди других ответов:
"Примечание
"Возвращаемый тип метода не является частью сигнатуры метода в целях перегрузки метода. Однако он является частью сигнатуры метода при определении совместимости между делегатом и методом, на который он указывает"