The first generic argument to Action
is contravariant not covariant. Action<ICommand>
is not a sub-type of Action<SomeCommand>
. In fact, it's the other way around. Action<SomeCommand>
is a sub type of Action<ICommand>
!
Right now you have an action that can take only a SomeCommand
. If you could cast it to Action<ICommand>
then someone could pass in an EvilCommand
, but an EvilCommand
is not a type of SomeCommand
. On the other hand, if you've written a method that can accept any type of ICommand
, then obviously you could pretend that it was a method that only accepts SomeCommand
objects, because you know all of them will implement ICommand
.
Your first solution works because you're introducing the explicit cast of the parameter. You're creating a new method, one that performs the specific type check needed. In addition to working, it is also the correct design in this specific case; it's one of those rare situations where you know that the object is in fact a TCommand
instance, not just an ICommand
, but the compiler can't prove it, and there aren't any really good ways of re-designing the application such that it could statically verify that.