[英]C# Covariance and Contravariance
I have classes Message1D
and Message2D
both inherit from Message
: 我有类
Message1D
和Message2D
都继承自Message
:
public abstract class Message {}
public class Message1D : Message {}
public class Message2D : Message {}
An interface IFoo
and classes Bar
and Baz
, which implement it: 实现它的接口
IFoo
和类Bar
和Baz
:
public interface IFoo<out G, in T>
where G : Message
where T : Message
{
G PassMessage(T input);
}
public class Bar : IFoo<Message1D, Message1D>
{
public Message1D PassMessage(Message1D input)
{
throw new NotImplementedException();
}
}
public class Baz : IFoo<Message2D, Message2D>
{
public Message2D PassMessage(Message2D input)
{
throw new NotImplementedException();
}
}
And my problem is here. 我的问题在这里。 How can I add Foo and Bar instances to the list ?
如何将Foo和Bar实例添加到列表中?
public class Network
{
private List<IFoo<Message, Message>> messages = new List<IFoo<Message, Message>>();
public void AddBar()
{
messages.Add(new Bar());
}
public void AddBaz()
{
messages.Add(new Baz());
}
}
I have an exception: 我有一个例外:
Can not convert
Bar
toIFoo<Message,Message>
无法将
Bar
转换为IFoo<Message,Message>
and 和
Can not convert
Baz
toIFoo<Message,Message>
无法将
Baz
转换为IFoo<Message,Message>
How can I add Bar
and Baz
instances to the List ? 如何将
Bar
和Baz
实例添加到列表中?
How can I add Bar and Baz instances to the List?
如何将Bar和Baz实例添加到列表中?
You can't, because you're trying to treat the input message as if it's covariant, but it's contravariant. 你不能,因为你试图将输入消息视为协变,但它是逆变的。 You can treat an
IFoo<Message1D, Message>
as an IFoo<Message, Message>
, but you can't treat an IFoo<Message, Message1D>
as an IFoo<Message, Message>
. 您可以将
IFoo<Message1D, Message>
视为IFoo<Message, Message>
,但不能将IFoo<Message, Message1D>
视为IFoo<Message, Message>
。 If that were valid, then someone would be allowed to pass in 2D messages into your object that can only handle 1D messages. 如果这是有效的,那么将允许某人将2D消息传递到只能处理1D消息的对象中。
As @Servy mentioned, it is not possible in your current architecture and you should probably remake it. 正如@Servy所提到的,在您当前的架构中是不可能的,您应该重新制作它。
But if somehow you can guarantee type safety, then you can try to explicitly implement IFoo<Message1D, Message>
in addition to IFoo<Message1D, Message1D>
as follows: 但是如果你能保证类型安全,那么你可以尝试显式实现
IFoo<Message1D, Message>
以及IFoo<Message1D, Message1D>
,如下所示:
public class Bar : IFoo<Message1D, Message1D>, IFoo<Message1D, Message>
{
public Message1D PassMessage(Message1D input)
{
// ...
}
Message1D IFoo<Message1D, Message>.PassMessage(Message input)
{
try
{
return PassMessage((Message1D) input);
}
catch (InvalidCastException)
{
// Message2D passed, handling exception
// ...
}
}
Similarly implement IFoo<Message2D, Message>
for Baz
. 类似地为
Baz
实现IFoo<Message2D, Message>
。
That will make your code work, but it is most likely not the best decision for you. 这将使您的代码工作,但它很可能不是您的最佳决定。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.