Domanda

I am not sure if I am missing something or just not understanding the way in which the complier works... Basically I want to be able to pass an action with a constrained parameter without having to recast it. Take the below code with the cast which works:

    private readonly Dictionary<Type, Action<ICommand>> _dictionary = new Dictionary<Type, Action<ICommand>>();

    public void Register<TCommand>(Action<TCommand> action) where TCommand : ICommand
    {
        _dictionary.Add(typeof(TCommand), x => action((TCommand)x));
    }

The following throws an error and says that a parameter of TCommand can't be passed as an ICommand

    public void Register<TCommand>(Action<TCommand> action) where TCommand : ICommand
    {
        _dictionary.Add(typeof(TCommand), action);
    }

Am I doing something wrong or is it that the where constraint is only understood by the method signature and the rest of the code ignores this directive?

È stato utile?

Soluzione

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.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top