C# 协变和逆变



我有类Message1DMessage2D都继承自Message

public abstract class Message {}
public class Message1D : Message {}
public class Message2D : Message {}

一个接口IFoo和类BarBaz,实现它:

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>

如何将BarBaz实例添加到列表中?

如何将 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>

这将使您的代码正常工作,但这很可能不是您的最佳决定。

相关内容

  • 没有找到相关文章

最新更新