Should the compiler see that in fact my first delegate type demands the argument to be at least of type ICommand, assuring that the delegate instance conforms to the signature of the second delegate type as well?
There are two problems here.
Firstly, delegate variance doesn't allow for an implicit reference conversion of one delegate type to another - it allows you to create a new delegate instance from a compatible existing one.
Secondly, you've got the variance the wrong way round CommandHandler<TCommand>
will only accept a specific type of command... whereas ICommandHandler
will accept any ICommand
.
So suppose we could do this:
CommandHandler<FooCommand> fooHandler = HandleFoo;
ICommandHandler generalHandler = new ICommandHandler(fooHandler);
Then we could call:
generalHandler(new BarCommand());
... how would you expect the HandleFoo
method to cope with that?
There is a conversion from ICommandHandler
to CommandHandler<TCommand>
for any particular TCommand
, because when the new delegate is called, that will always be valid. Sample code:
using System;
delegate void CommandHandler<TCommand>(TCommand command)
where TCommand : ICommand;
delegate void ICommandHandler(ICommand command);
interface ICommand {}
class Command : ICommand {}
class Test
{
public static void Main()
{
ICommandHandler x = null;
CommandHandler<Command> y = new CommandHandler<Command>(x);
}
}
I suggest you just change your dictionary to:
Dictionary<Type, Delegate> mCommandHandlers;
Then when you need to invoke any particular delegate, you'll need to cast to the right kind of handler - which I assume you'll know due to a type parameter at that point. Or you could create a proxy handler which performs the cast, as per Jared's answer.