我有以下界面:
public interface ICommand<TMessage>
where TMessage : MessageBase
{
TMessage Message { get; set; }
}
我希望能够将实现转换为IMessage,但为了实现这一点,type参数需要是协变的,如下所示:
public interface ICommand<out TMessage>
where TMessage : MessageBase
{
TMessage Message { get; set; }
}
然后,编译器抱怨:类型参数'TMessage'必须在ICommand.Message'上不变地有效。 'TMessage'是协变的。 如果我删除了setter,一切正常。
但是,我不明白为什么这个setter在理论上会出现问题,因为我已经指定Message属性只能保留对更多派生类型的MessageBase实例的引用...
答案 0 :(得分:2)
没关系,经过多思考后,实际上很容易看到。
假设我实例化DerivedCommand<T>
(实现ICommand<T>
)
var derivedCommand = new DerivedCommand<DerivedMessage>();
然后将其投放到ICommand<MessageBase>
var command = (ICommand<MessageBase>) derivedCommand;
这意味着我现在可以将任何类型MessageBase
的实例分配给Message属性。但是,由于该属性实际上是DerivedMessage
类型,其派生的结果比MessageBase
更多,因此它并不适用于所有情况(其中AnotherMessage
派生自MessageBase
但不是来自DerivedMessage
> HISTTIMEFORMAT="%d/%m/%y %T "
> history
)。因此,即使类型受到约束,setter也不能协变。