我想维护一个代表列表(这里:“mCommandHandlers”)。由于它们是通用委托,我实际上定义了第二种类型的委托,以便我可以维护这样的列表:
public delegate void CommandHandler<TCommand>(TCommand command) where TCommand : ICommand;
public delegate void ICommandHandler(ICommand command);
Dictionary<Type, ICommandHandler> mCommandHandlers;
我会使用第一种类型来获得编译时的优点,例如确切知道在我的委托的实现中使用了哪种TCommand:
RegisterHandler<ResourceCommand>((command) =>
{
if (command != null)
{
ResourceManager.ResourceReceived(command.ResourceName, command.ResourceHash, command.ResourceData);
}
});
在RegisterHandler中,我现在想做以下事情:
public void RegisterHandler<TCommand>(CommandHandler<TCommand> handler) where TCommand : ICommand
{
mCommandHandlers.Add(typeof(TCommand), handler);
}
但是我收到以下错误消息:
错误3参数2:无法转换
CommandHandler<TCommand>'
来'ICommandHandler'
这是为什么?编译器是否应该看到实际上我的第一个委托类型要求参数至少是ICommand类型,同时确保委托实例也符合第二个委托类型的签名?
答案 0 :(得分:3)
问题是两个委托类型根本不兼容。为了完成这项工作,您需要添加一个间接层,用于转换ICommand
和TCommand
之间的参数。
public void RegisterHandler<TCommand>(CommandHandler<TCommand> handler)
where TCommand : ICommand
{
mCommandHandlers.Add(
typeof(TCommand),
(command) => handler((TCommand)command);
);
}
答案 1 :(得分:2)
编译器是否应该看到实际上我的第一个委托类型要求参数至少是ICommand类型,同时确保委托实例也符合第二个委托类型的签名?
这里有两个问题。
首先,委托方差不允许将一个委托类型隐式引用转换为另一个委托类型 - 它允许您从兼容的现有委托创建新委托实例。
其次,你得到的方差是错误的,CommandHandler<TCommand>
只会接受特定的类型的命令...而ICommandHandler
会接受任何 ICommand
。
假设我们可以这样做:
CommandHandler<FooCommand> fooHandler = HandleFoo;
ICommandHandler generalHandler = new ICommandHandler(fooHandler);
然后我们可以打电话:
generalHandler(new BarCommand());
...您希望HandleFoo
方法如何应对?
对于任何特定的ICommandHandler
, 是从CommandHandler<TCommand>
到TCommand
的转换,因为当调用新的委托时,它始终有效。示例代码:
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);
}
}
我建议您将字典更改为:
Dictionary<Type, Delegate> mCommandHandlers;
然后当你需要调用任何特定的委托时,你需要转换为正确的处理程序 - 我假设你知道由于那时的类型参数。或者你可以根据Jared的回答创建一个执行演员表的代理处理程序。