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.