简体   繁体   中英

C# Adding a derived generic type to a Dictionary or List

when I try the following in C#, I get an NPE. It's likely not how this should work:

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>);

  ...
}

Without the as I get compiler errors and with it, it just adds a null to the List. I should note that Subscription and Event are both interfaces. In Java I would simply say <? extends Event> <? extends Event> or <? extends Subscription<?>> <? extends Subscription<?>> and this would work with no issues.

Any help on this matter is greatly appreciated!

Generic delegates do not guarantee matching signatures.

What would happen if the Subscribe<T>(Action<T>) were to invoke the Action<T> with a concrete implementation?

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>);
}

This would result in a compiler error.

Whether the method signature expects a concrete subtype, or the Event base type, we can not say. The only thing we can say for certain, is that the method takes an argument which implements Event .

Therefore, we need to change the Subscribe method so the signature of Action<T> is known. Since the Action<T> delegate is contravariant , meaning that you can pass any subtype of T into the action, we can change the signature to Action<Event> .

public void Subscribe(Action<Event> action)
{
  subscriptionMap[type].Add(new DefaultSubscription<Event>(action));
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM