我有类Message1D
和Message2D
都继承自Message
:
public abstract class Message {}
public class Message1D : Message {}
public class Message2D : Message {}
一个接口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();
}
}
我的问题就在这里。如何将 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());
}
}
我有一个例外:
无法将
Bar
转换为IFoo<Message,Message>
和
无法将
Baz
转换为IFoo<Message,Message>
如何将Bar
和Baz
实例添加到列表中?
如何将 Bar 和 Baz 实例添加到列表中?
你不能,因为你试图将输入消息视为协变,但它是逆变的。 您可以将IFoo<Message1D, Message>
视为IFoo<Message, Message>
,但不能将IFoo<Message, Message1D>
视为IFoo<Message, Message>
。 如果这是有效的,那么将允许某人将 2D 消息传递到只能处理 1D 消息的对象中。
正如@Servy提到的,这在你当前的架构中是不可能的,你应该重新制作它。
但是,如果您以某种方式可以保证类型安全,那么除了IFoo<Message1D, Message1D>
之外,您还可以尝试显式实现IFoo<Message1D, Message>
,如下所示:
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
// ...
}
}
同样,为Baz
实现IFoo<Message2D, Message>
。
这将使您的代码正常工作,但这很可能不是您的最佳决定。