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,我会得到编译器错误,而有了它,它只会向列表中添加一个空值。我应该注意到 SubscriptionEvent 都是接口。在 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));
}