簡體   English   中英

C#協方差和逆變

[英]C# Covariance and Contravariance

我有類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, 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
            // ...
        }
    }

類似地為Baz實現IFoo<Message2D, Message>

這將使您的代碼工作,但它很可能不是您的最佳決定。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM