使用可变类型参数的 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
.
为什么这行不通,我该如何让它工作?在这种情况下,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
.