0

我被卡住了,为什么这不起作用:

  var childAction = new Action<CancelCommand>(blabla);
  Action<IDomainCommand> upperAction = (Action<IDomainCommand>) childAction;

如果 CancelCommand 实现了 IDomainCommand,为什么这不起作用?顺便说一句:这是我在这里想要做的协变还是逆变?;)

提前谢谢你,最好的劳林

编辑 谢谢你们的快速回复!

我需要这个的问题是因为我构造了一个通用的动作模板。我有以下界面:

IMessageBus.RegisterAction<T>(Action<T> registerAction) where T : IDomainCommand

因为我必须在运行时构建此操作,所以我的代码如下所示:

var genericExecuteAction = this.GetType().GetMethod("ExecuteCommandAction",
                                                            BindingFlags.NonPublic | BindingFlags.Instance).MakeGenericMethod(commandType);

var actionType = typeof(Action<>).MakeGenericType(commandType);
var @delegate = Delegate.CreateDelegate(actionType, this, genericExecuteAction);
var actionDelegate = (Action<DomainCommandBase>)@delegate;

messageBus.Register(actionDelegate);

问题是我需要转换它以便我可以将它传递给这个方法。你看?我们使用的消息总线背后是使用 RX,不幸的是那里的所有方法都使用泛型,现在有一个非泛型重载。

4

4 回答 4

1

的类型参数Action是逆变的:您可以将 an 分配给 an Action<object>Action<string>因为显然可以在任何对象上工作的方法也可以在字符串上工作。

您在这里所做的是尝试将适用于CancelCommand(派生类型)的方法计为适用于任何IDomainCommand(基本类型)的方法。这在逻辑上是错误的,所以编译器不允许你这样做——如果是这样,你可以调用upperAction传递给它一个DifferentTypeOfDomainCommand.

于 2012-09-26T09:09:23.327 回答
0

等等,你为什么要这个工作?

childAction是接受 aCancelCommand并用它做某事的东西。

upperAction可以在任何 IDomainCommand上调用,而不仅仅是CancelCommand. 假设以上编译;当我这样做时应该发生什么

upperAction(new EditCommand());

在哪里class EditCommand : IDomainCommand

如果您尝试相反的分配:

        var upperAction = new Action<IDomainCommand>(idc => { });
        Action<CancelCommand> childAction = upperAction;

它有效,您甚至不需要演员表。任何都Action<IDomainCommand>算作Action<CancelCommand>.

于 2012-09-26T09:10:38.787 回答
0

这是逆变。这是行不通的,因为如果可以的话,您可以编写如下内容:

interface IDomainCommand { }
class CancelCommand : IDomainCommand { }
class AcceptCommand : IDomainCommand { }

        Action<CancelCommand> a1 = c => { };
        Action<IDomainCommand> a2 = a1;

        var acceptCommand = new AcceptCommand();

        a2(acceptCommand); // what???

a2指向a1,并且 a1 不能接受AcceptCommand参数,因为它不是 a CancelCommand

于 2012-09-26T09:09:57.053 回答
0

您忘记了如何使用这些代表

var childAction = new Action<CancelCommand>(blabla);
Action<IDomainCommand> upperAction = (Action<IDomainCommand>) childAction;

意味着upperAction将在将来的某个时间点被调用,传递某种形式的IDomainCommand对象。你给它一个只能处理CancelCommand对象的函数。但是(可能)还有其他实现 的类IDomainCommand,并且upperAction可以用它们中的任何一个来调用。

于 2014-08-22T14:46:05.560 回答