【问题标题】:C# Cast class with variable type parameter. Code snippet explains it具有可变类型参数的 C# Cast 类。代码片段解释了它
【发布时间】:2015-07-11 21:55:42
【问题描述】:

为什么这不起作用,我该如何使它起作用?在这种情况下,M 直接实现 IMessage,我得到一个 InvalidCastException

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

M 实现IMessage 时,不应该将IMessageListener&lt;M&gt; 转换为IMessageListener&lt;IMessage&gt; 工作吗?

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

//编辑 IMessageListener 类如下所示:

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

【问题讨论】:

  • 糟糕!很抱歉这个误导性的答案 - 我只是根据我以前读过的东西发布它。希望这个答案对您有所帮助 - stackoverflow.com/questions/19166133
  • 为什么需要投射它?只需将其用作IMessageListener&lt;IMessage&gt; - 稍后致电listener.ProcessMessage(message)

标签: c# type-conversion type-parameter


【解决方案1】:

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

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&lt;MessageA&gt;?将MessageAListener 转换为IMessageListener&lt;IMessage&gt;,然后您可以将其传递给MessageB

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


这不起作用,因为IMessageListener&lt;T&gt;T 上是逆变 - 它仅将T 引用为输入。因此,您可以将IMessageListener&lt;IMessage&gt; 转换为IMessageListener&lt;MessageA&gt;,因为它会很乐意接受MessageA 作为输入,而不是IMessage

您要执行的演员表要求IMessageListener&lt;T&gt;T 上是协变 - 它必须引用T 作为输出。然后,您可以将 IMessageListener&lt;MessageA&gt; 转换为 IMessageListener&lt;IMessage&gt;,因为真正的返回类型 MessageA 可以转换为预期的返回类型 IMessage

【讨论】:

  • 好的,我明白了。我的问题是,我有一个字典,其中一个类型作为键,一个类型的实例列表作为值,它实现了 IMessage。那我该如何实现呢?
  • 你知道我可以在哪里阅读更多关于协方差的信息吗?它对我来说是全新的
  • @Zoidy 混合泛型和类型对象通常是一个错误。泛型在编译时处理不同的类型; type 对象在运行时处理不同的类型。 Eric Lippert 从here 开始有一个很好的协方差系列。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-06
  • 2023-03-08
相关资源
最近更新 更多