Я знаю, что модификатор params
(который превращается в один параметр типа массива в так называемый «массив параметров»), в частности, не является частью сигнатуры метода. Теперь рассмотрим этот пример:Изменение модификатора params в переопределении метода
class Giraffid
{
public virtual void Eat(int[] leaves)
{
Console.WriteLine("G");
}
}
class Okapi : Giraffid
{
public override void Eat(params int[] leaves)
{
Console.WriteLine("O");
}
}
Это компилируется без предупреждений. Потом сказал:
var okapi = new Okapi();
okapi.Eat(2, 4, 6); // will not compile!
выдает ошибку (No overload for method 'Eat' takes 3 arguments
).
Теперь я знаю, что компилятор переводит модификатор params
в приложение System.ParamArrayAttribute
на соответствующий параметр. В общем случае нет никакой проблемы при применении одной коллекции атрибутов к параметру виртуального метода, а затем декорирования «соответствующего» параметра в переопределяющем методе в производном классе с другим набором атрибутов.
Однако компилятор решительно игнорирует ключевое слово params
. И наоборот, если сделать это наоборот, и применяет params
к параметру в базовом классе Giraffid
, а затем опускает ключевое слово в переопределении в Okapi
, компилятор решает украсить как методами с System.ParamArrayAttribute
. Конечно, я проверял эти вещи с IL DASM.
Мой вопрос:
Является ли это документально поведение? Я тщательно изучил спецификацию языка C#, не найдя упоминания об этом.
Я могу сказать, что по крайней мере среда разработки Visual Studio смущена этим. При вводе 2, 4, 6
в вышеупомянутом методе вызов intellisense показывает мне void Okapi.Eat(params int[] leaves)
в конце.
Для Comparision, я также попытался реализация метод интерфейса и изменяя наличие/отсутствие params
в интерфейсе и реализация класса, и я попытался определение типа делегата и изменение params
или нет ни в определении типа делегата или метод, группа методов которого я назначен переменной моего типа делегата. В этих случаях было вполне возможно изменить params
-ness.
Обратите внимание, что это также отвечает за то, почему он работает только с интерфейсами (пример кода в двух экземплярах в http://stackoverflow.com/questions/27843804/compiling-generic-interface-vs-generic-abstract-class-params-keyword) - нет «переопределить», поэтому метод с параметрами '* не исключается * из списка возможных совпадений. –