簡體   English   中英

約束泛型類型參數的逆解

[英]Contravariance on constrained generic type parameters

參考在Visual Studio 2010 Express中為C#編譯的這個測試代碼

public class Test
{
    class Base { }
    class Derived : Base { }

    void Test1(IEnumerable<Derived> derived)
    {
        IEnumerable<Base> b = derived; //This works fine using covariance on IEnumerable
    }

    void Test2<TDerived, TBase>(TDerived derived) where TDerived : TBase
    {
        TBase b = derived; //This works fine because TDerived is constrained to derive from TBase
    }

    void Test3<TDerived, TBase>(IEnumerable<TDerived> derived) where TDerived : TBase
    {
        IEnumerable<TBase> b = derived; //ERROR: paraphrased: Cannot implicitly convert type IEnumerable<TDerived> to IEnumerable<TBase>
    }
}

我試圖利用IEnumerable的協方差將一個泛型類型參數的可枚舉存儲在該類型參數被約束為繼承的類的可枚舉中。 這由Test3舉例說明。 請注意,Test1和Test2(分別演示編譯時類型的協方差和約束類型的賦值)都可以正常編譯。 它是兩種語言功能的組合,對我來說不起作用。

我能夠使用IEnumerable<TBase> b = derived.Cast<TBase>()並且100%確信如果我的理解沒有缺陷,任何演員都不會失敗,所以我確實有一個可用的解決方法。 我的問題是,為什么編譯器不允許這樣做? 出於某些邏輯原因,編譯器中的疏忽或其他我沒有想到的其他原因,這是否被禁止?

回答最初的問題

您當前正在嘗試將TDerived類型的單個元素轉換為Base類型的序列 我不希望你的Cast調用工作,因為TDerived沒有實現IEnumerable - 我懷疑你實際上已經TDerived在不同的情況下工作了。

我懷疑你實際上意味着:

void Test3<TDerived>(IEnumerable<TDerived> derived) where TDerived : Base
{
    IEnumerable<Base> b = derived;
}

這沒有任何問題。

回答編輯過的問題

好的,現在我們在兩個類型參數之間遇到了真正的問題,問題是編譯器不知道它們是引用類型 - 這是泛型方差所必需的。 您可以使用TDerived上的class約束來修復它:

void Test3<TDerived, TBase>(IEnumerable<TDerived> derived)
    where TDerived : class, TBase
{
    IEnumerable<TBase> b = derived;
}

暫無
暫無

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

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