Action lambda 中的逆变 - C#

发布于 2024-10-17 08:09:32 字数 855 浏览 7 评论 0原文

我有一个像这样的类层次结构,

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 实例。

任何帮助或指示,非常感谢。

I have a class hierarchy like this

public abstract class CalendarEventBase{}

public class TrainingEvent : CalendarEventBase{}

public class AuditEvent : CalendarEventBase{}

I wanted to create an action Action lamda that had a generic type paramater of type CalendarEventBase that I could assign to the following different methods:

public void EmailCancelation(TrainingEvent trainingEvent)

public void EmailCancelation(AuditEvent auditEvent)

I created the following illegal assignment:

Action<CalendarEventBase> emailCancelation = _trainingService.EmailTrainingCancellation;

The compiler complains that it was expecting a method with void(CalendarEventBase) as a signature. I was surprised by this as I thought it would accept a more derived type.

To get round this, I created the following delegate that allows me to complete my task:

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

My question is, could I have completed the task without having to create an additional delegate? I thought I could just create an Action instance.

Any help or pointers, greatly appreciated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

浅黛梨妆こ 2024-10-24 08:09:32

该行:

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; 

The line:

Action<CalendarEventBase> emailCancelation = _trainingService.EmailTrainingCancellation;

is actually expecting covariance, not contravariance. But that logically doesn't make sense; the method expects a TrainingEvent as input - how can you pass a more general type (CalendarEventBase) to it?

This isn't legal:

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

but this is fine:

// Anything that you want to with an animal, you can do with a mammal.
Action<Mammal> mammalAction = MethodThatTakesAnAnimal; 
醉殇 2024-10-24 08:09:32

lambda 无法支持这一点,因为您声明的 emailCancelation 变量将接受 CalendarEventBase,但实际实现将仅接受 TrainingEvent。如果有人使用 AuditEvent 参数调用 emailCancelation 会发生什么?

The lambda can't support this, because the emailCancelation variable you've declared will accept a CalendarEventBase, but the actual implementation will only accept the TrainingEvent. What would happen if someone were to call emailCancelation with an AuditEvent parameter?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文