Я могу присвоить метод M
делегировать объект d
с менее определенным типом параметра, но когда я хочу присвоить анонимный метод с тем же подпись как метод M
кому: d
, Я получаю ошибку.
Почему это?
class derivedEventArgs : EventArgs { }
delegate void newDelegate(object o, derivedEventArgs e);
static void Main(string[] args)
{
newDelegate d = M; // ok
d = (object o, EventArgs e) => { }; // error
}
public static void M(object o, EventArgs e) { }
Джаред, конечно, прав, что это сделано намеренно.
Причина такого дизайна в том, что в случае преобразования контравариантного метода у вас может быть метод, который вы не писали, и который вы назначаете переменной делегата, которую вы тоже не писали. Вы не контролируете типы. Поэтому мы немного смягчим вас и позволим параметрам совпадать контравариантно, а типы возвращаемых значений совпадать ковариантно.
При преобразовании лямбда-выражения в делегат вы управляете назначенным объектом. Ничто не мешает сделать его точным совпадением по типам параметров, и поэтому мы требуем сделать это. Здесь нельзя жульничать.
Это описано в разделе 6.5 спецификации языка C #. Если вы явно вводите параметры анонимной функции, они должны совпадать как по типу, так и по модификаторам, чтобы быть совместимыми сигнатурами.
В частности, тип делегата D совместим с предоставленной анонимной функцией F
...
Если F имеет явно типизированный список параметров, каждый параметр в D имеет тот же тип и модификаторы, что и соответствующий параметр в F.