Контравариантность в действии лямбда - C # - PullRequest
5 голосов
/ 11 февраля 2011

У меня есть иерархия классов, подобная этой

public abstract class CalendarEventBase{}

public class TrainingEvent : CalendarEventBase{}

public class AuditEvent : CalendarEventBase{}

Я хотел создать действие Action lamda, у которого был универсальный типовой параметр типа CalendarEventBase, который я мог бы назначить для следующих различных методов:

public void EmailCancelation(TrainingEvent trainingEvent)

public void EmailCancelation(AuditEvent auditEvent)

Я создал следующее недопустимое назначение:

Action<CalendarEventBase> emailCancelation = _trainingService.EmailTrainingCancellation;

Компилятор жалуется, что ожидал метод с void (CalendarEventBase) в качестве подписи.Я был удивлен этим, поскольку думал, что он примет более производный тип.

Чтобы обойти это, я создал следующий делегат, который позволит мне выполнить мою задачу:

public delegate void EmailCancelation<in T>(T calendarEvent) where T : CalendarEventBase;

МойВопрос в том, мог ли я выполнить задачу, не создавая дополнительного делегата?Я думал, что смогу просто создать экземпляр Action.

Любая помощь или указатели, с благодарностью.

Ответы [ 2 ]

7 голосов
/ 11 февраля 2011

Линия:

Action<CalendarEventBase> emailCancelation = _trainingService.EmailTrainingCancellation;

фактически ожидает ковариацию , а не контравариантность .Но это логически не имеет смысла;метод ожидает TrainingEvent в качестве входных данных - как вы можете передать ему более общий тип (CalendarEventBase)?

Это недопустимо:

// What if the method wants to make the lion roar but you pass in a goat?
Action<Mammal> mammalAction = MethodThatTakesALion; 

но это нормально:

// Anything that you want to with an animal, you can do with a mammal.
Action<Mammal> mammalAction = MethodThatTakesAnAnimal; 
1 голос
/ 11 февраля 2011

Лямбда не может поддерживать это, потому что объявленная вами переменная emailCancelation будет принимать CalendarEventBase, но фактическая реализация будет принимать только TrainingEvent. Что произойдет, если кто-то вызовет emailCancelation с параметром AuditEvent?

...