С Использование дисперсии в делегатах (C #) :
Когда вы назначаете делегату метод, ковариация и контравариация обеспечивают гибкость при сопоставлении типа делегата с сигнатурой метода. Ковариация позволяет методу иметь возвращаемый тип, который является более производным, чем тот, который определен в делегате. Контравариантность разрешает метод с типами параметров, которые являются менее производными, чем типы делегатов.
Можно присвоить DoSomethingBy_MyParent
processor
( контравариантное назначение, поскольку MyParent
менее производно, чем MyChild
), поскольку все, что является MyChild
, по определению также MyParent
Action<MyChild> processor;
processor = DoSomethingBy_MyParent;
Однако то, что происходит, когда вы пытаетесь передать MyParent
в processor
, эффективно
Action<MyChild> processor;
processor(new MyParent());
Это нехорошо, потому что processor
требует, чтобы в него было передано MyChild
- его нельзя назвать контравариантно. Неважно, что вы присвоили ему DoSomethingBy_MyParent
- processor
объявлен как Action<MyChild>
, поэтому должен получить экземпляр MyChild
или более производный тип.
Другими словами, у вас есть
public void DoSomethingBy_MyChild(MyChild myChild) { //code }
и вы не ожидаете, что сможете назвать его так:
DoSomethingBy_MyChild(new Parent());
потому что вызовы методов работают ковариантно (вы можете передать экземпляр более производного типа), а не контравариантно (вы не можете передать экземпляр менее производного типа).