使用可变类型参数的 C# Cast class。代码片段解释了它

C# Cast class with variable type parameter. Code snippet explains it

为什么这行不通,我该如何让它工作?在这种情况下,M 直接实现了 IMessage,我得到一个 InvalidCastException.

public void Subscribe<M>(IMessageListener<M> listener) where M : IMessage
{
    IMessageListener<IMessage> l = (IMessageListener<IMessage>)listener;
}

M 实现 IMessage 时,不应该将 IMessageListener<M> 转换为 IMessageListener<IMessage> 吗?

抱歉标题不好,不知道怎么形容。

//编辑 IMessageListener class 看起来像这样:

public interface IMessageListener<M> where M : IMessage
{
    void ProcessMessage(M message);
}

简短回答:不,它不应该起作用。

public class MessageA : IMessage
{
    public int SpecificAField;
}

public class MessageB : IMessage {}

public class MessageAListener : IMessageListener<MessageA>
{
    public void ProcessMessage(MessageA message)
    {
        messageA.SpecificAField = 3;
    }
}

如果编译器让Subscribe<MessageA>?将 MessageAListener 转换为 IMessageListener<IMessage>,然后您可以将其传递给 MessageB.

然后 MessageAListener 会尝试在 MessageB 上设置 SpecificAField,但它没有。


这不起作用,因为 IMessageListener<T>T 上是 逆变 - 它引用 T 仅作为 输入。因此,您可以将 IMessageListener<IMessage> 转换为 IMessageListener<MessageA>,因为它会很乐意接受 MessageA 作为 输入 代替 IMessage .

您要执行的转换需要 IMessageListener<T>T 协变 - 它必须仅引用 T 作为输出。然后,您可以将 IMessageListener<MessageA> 转换为 IMessageListener<IMessage>,因为真正的 return 类型 MessageA 可以转换为预期的 return 类型 IMessage.