C# 将派生泛型类型添加到字典或列表
C# Adding a derived generic type to a Dictionary or List
当我在 C# 中尝试以下操作时,出现 NPE。这可能不是它应该如何工作的:
private readonly Dictionary<Type, List<Subscription<Event>>> subscriptionMap = new Dictionary<Type, List<Subscription<Event>>>();;
public void Subscribe<T>(Action<T> action) where T : Event {
...
subscriptionMap[type].Add(new DefaultSubscription<T>(action) as Subscription<Event>);
...
}
如果没有 as
,我会得到编译器错误,而有了它,它只会向列表中添加一个空值。我应该注意到 Subscription
和 Event
都是接口。在 Java 中,我会简单地说 <? extends Event>
或 <? extends Subscription<?>>
,这不会有任何问题。
非常感谢对此问题的任何帮助!
通用委托不保证匹配签名。
如果 Subscribe<T>(Action<T>)
使用具体实现调用 Action<T>
会发生什么情况?
Subscribe<ConcreteEvent>((ConcreteEvent e) => { });
...
private void Subscribe<T>(Action<T> action)
where T : Event
{
action(new Event()); // Does not match method signature
subscriptionMap[type].Add(new DefaultSubscription<T>(action) as Subscription<Event>);
}
这会导致编译器错误。
方法签名是否需要具体的子类型,或者 Event
基类型,我们不能说。我们唯一可以肯定地说的是,该方法采用实现 Event
.
的参数
因此,我们需要更改 Subscribe
方法,以便知道 Action<T>
的签名。由于 Action<T>
委托是 contravariant,这意味着您可以将 T
的任何子类型传递给操作,我们可以将签名更改为 Action<Event>
.
public void Subscribe(Action<Event> action)
{
subscriptionMap[type].Add(new DefaultSubscription<Event>(action));
}
当我在 C# 中尝试以下操作时,出现 NPE。这可能不是它应该如何工作的:
private readonly Dictionary<Type, List<Subscription<Event>>> subscriptionMap = new Dictionary<Type, List<Subscription<Event>>>();;
public void Subscribe<T>(Action<T> action) where T : Event {
...
subscriptionMap[type].Add(new DefaultSubscription<T>(action) as Subscription<Event>);
...
}
如果没有 as
,我会得到编译器错误,而有了它,它只会向列表中添加一个空值。我应该注意到 Subscription
和 Event
都是接口。在 Java 中,我会简单地说 <? extends Event>
或 <? extends Subscription<?>>
,这不会有任何问题。
非常感谢对此问题的任何帮助!
通用委托不保证匹配签名。
如果 Subscribe<T>(Action<T>)
使用具体实现调用 Action<T>
会发生什么情况?
Subscribe<ConcreteEvent>((ConcreteEvent e) => { });
...
private void Subscribe<T>(Action<T> action)
where T : Event
{
action(new Event()); // Does not match method signature
subscriptionMap[type].Add(new DefaultSubscription<T>(action) as Subscription<Event>);
}
这会导致编译器错误。
方法签名是否需要具体的子类型,或者 Event
基类型,我们不能说。我们唯一可以肯定地说的是,该方法采用实现 Event
.
因此,我们需要更改 Subscribe
方法,以便知道 Action<T>
的签名。由于 Action<T>
委托是 contravariant,这意味着您可以将 T
的任何子类型传递给操作,我们可以将签名更改为 Action<Event>
.
public void Subscribe(Action<Event> action)
{
subscriptionMap[type].Add(new DefaultSubscription<Event>(action));
}