Action delegates are contravariant β the type is defined as Action<in T> . This implies how the principle of substitution works when applied to actions.
Consider two types: B (base) and D (received). Then Action<B> more output than Action<D> . This implies the following behavior:
class B { } class D : B { } ... Action<D> derivedAction = ... Action<B> baseAction = derivedAction;
In your example, when SpecialEvent is a type derived from EventBase , you are allowed to assign Action<SpecialEvent> = Action<EventBase> , but not vice versa (as you try).
Since you are already checking the type of event before storing delegates in the dictionary, you do not need to insist on storing strongly typed delegates, not to mention that you cannot insist on strong printing due to the contravariance of Action delegates.
You can store everything you like in the dictionary, for example. Delegate or plain object , and then go down to a specific Action<T> when it comes time to select an Action delegate from the collection.
public class FooHandler { internal Dictionary<Type, object> _validTypes = new Dictionary<Type, object>(); internal void RegisterFor<T>(Action<T> handlerFcn) where T: EventBase { _validTypes.Add(typeof(T), handlerFcn); } internal Action<T> Find<T>() where T : EventBase => (Action<T>)_validTypes[typeof(T)]; }
Zoran horvat
source share