[英]C# infer Type from Generic with constraint
I'm trying to register a generic that derives from a base class in the following way, but getting the error : 我正在尝试以以下方式注册从基类派生的泛型,但出现错误:
cannot convert
MyCallback<T>
expression to typeMyCallback<Event>
无法将MyCallback<T>
表达式转换为MyCallback<Event>
类型
I was hoping the constraints would make this possible but am I missing something? 我希望约束能够使之成为可能,但我缺少什么吗?
public class Event
{ };
public delegate void MyCallback<T>(T arg1) where T : Event;
static class EventDispatcher
{
public static Dictionary<string, MyCallback<Event>> eventTable = new Dictionary<string, MyCallback<Event>>();
static void RegisterCallback<T>(MyCallback<T> callback) where T : Event
{
eventTable.Add("test", callback);
}
}
You need to have the type parameter be part of the EventDispatcher
class: 您需要将type参数作为EventDispatcher
类的一部分:
public class EventDispatcher<T> : where T : Event {
public Dictionary<string, MyCallback<T>> eventTable = new Dictionary<string, MyCallback<T>>();
void RegisterCallback(MyCallback<T> callback) {
eventTable.Add("test", callback);
}
}
This is because the MyCallback<Event>
declared in eventTable
is not going to be compiled into the same type declared in RegisteredCallback
when written like your example. 这是因为在像您的示例那样编写时,在eventTable
声明的MyCallback<Event>
不会被编译成在RegisteredCallback
声明的相同类型。
When you have a MyCallback<Event>
you're saying that you have a method that can take any type of event. 当您拥有MyCallback<Event>
,就是说您拥有可以接受任何类型的事件的方法。 It can accept an EventOne
, or an EventTwo
, or a SomeOtherEvent
. 它可以接受EventOne
或EventTwo
或SomeOtherEvent
。
Let's say I call RegisterCallback
and pass in a delegate pointing to a method with this signature: 假设我调用RegisterCallback
并传入一个指向具有此签名的方法的委托:
public static void Foo(SomeOtherEvent arg)
If your code would work, and I could assign that to a MyCallback<Event>
, then I could pass in an EventOne
instance to that method when calling it. 如果您的代码可以运行,并且可以将其分配给MyCallback<Event>
,则可以在调用该方法时将EventOne
实例传递给该方法。 That's obviously a problem. 这显然是个问题。
There's a term for that; 这个有一个名词。 you're expecting MyCallback
to be covariant with respect to it's generic argument. 您期望MyCallback
就其通用参数而言是协变的。 In fact, it's contravariant . 实际上,这是反变的 。 If I have a method that can accept any type of event, I can clearly pass in a SomeEvent
, or a SomeOtherEvent
, meaning I could assign a MyCallback<Event>
to a MyCallback<SomeOtherEvent>
, rather than the other way around. 如果我有一个可以接受任何类型的事件的方法,则可以清楚地传递SomeEvent
或SomeOtherEvent
,这意味着我可以将MyCallback<Event>
分配给MyCallback<SomeOtherEvent>
,而不是相反。
If you want to tell the compiler that, "I know that this method cannot actually be called with any type of event, but I want you to allow this check and only fail at runtime if the given argument is not of the proper type." 如果您想告诉编译器,“我知道实际上不能用任何类型的事件来调用此方法,但是我希望您允许进行此检查,并且仅在给定参数类型不正确时在运行时失败。” then you can do that, assuming you actually have a way of ensuring you call each callback with the proper arguments. 那么,假设您确实有一种方法可以确保使用正确的参数调用每个回调, 就可以做到这一点。 You can't just do a cast either; 您也不能只进行演员表转换; you need to wrap the method in a new method that does the cast: 您需要将方法包装在执行强制转换的新方法中:
eventTable.Add("test", e => callback((T)e));
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.