簡體   English   中英

無法投射MyType <T> 到MyType <object>

[英]Unable to cast MyType<T> to MyType<object>

我得到的具體例外是:

無法將類型為NbtByte對象NbtByte為輸入INbtTag<System.Object>

在這一行:

tag = (INbtTag<object>)new NbtByte(stream);

tag聲明為:

INbtTag<object> tag;

NbtByte定義為:

public class NbtByte : INbtTag<byte>

IBtTag是:

public interface INbtTag<out T>

我想通過聲明它作為out T我將能夠做這樣的事情。

基本上,我想要一本IbtTag<T>字典,

var dict = new Dictionary<string, INbtTag<object>>();

但是T是不同類型的(因此我用object聲明它)。 這可能嗎?

接口差異僅適用於引用類型。 排除值類型(例如整數,字節等,以及自定義結構)。 例如,即使數組是IEnumerable<int> ,也不能將整數數組用作IEnumerable<object> IEnumerable<int>

IEnumerable<object> objs = new int[] { 1, 2, 3 }; // illegal
IEnumerable<object> objs = new string[] { "a", "b", "c" }; // legal

要解決字典問題,您可以選擇定義非泛型接口。 (如果您的通用接口可能將成員公開為類型T,則非泛型接口將僅顯示object 。)

說你有

interface INbtTag { } // non-generic interface 
interface INbtTag<out T> : INbtTag { } // covariant generic interface

然后你可以將你的字典用作Dictionary<string, INbtTag>

缺點是當您實現接口時,您必須實現這兩者。 這通常意味着隱式實現通用版本,而非顯式實現非通用版本。 例如:

interface INbtTag
{
    object GetValue(); 
}

interface INbtTag<out T> : INbtTag
{
    T GetValue();
}

class NbtByte : INbtTag<byte>
{
    byte value;

    public byte GetValue() // implicit implementation of generic interface
    {
        return value;
    }

    object INbtTag.GetValue() // explicit implementation of non-generic interface
    {
        return this.GetValue(); // delegates to method above
    }
}

使用泛型類型的一個限制方面是泛型類型在類型轉換中不像傳統類型那樣靈活。 List<Object>List<String>或任何其他對象類型的賦值不兼容。

Linq中有轉換輔助函數,例如.Cast<T>() ,它將邏輯上將每個元素從一個列表轉換為T類型,以形成List<T>類型的新列表。 雖然輔助函數很方便,但它並沒有改變List<N>List<T>不兼容的事實,即使N和T在某種程度上是類型兼容的。

從本質上講,泛型類型不是多態的。 在同一泛型類型的實例之間沒有通用類型 - 沒有類型可以聲明一個可以包含List<T>List<N>的變量。

如果您正在創建自己的泛型類型,並且您確實想要一些可用於攜帶泛型類型的所有表現形式的常見類型,則必須執行某些類型的體操以使其工作,並且您將受限制你可以做什么。 您需要定義基類或接口類型,然后需要使您的泛型類型繼承自基類或實現接口類型。 使用此配置,您可以使用基類類型或接口類型聲明變量,並可以將MyClass<N>MyClass<T>分配給同一個變量,只訪問基類中定義的成員(當然不會對N或T型參數有任何了解。

協變類型參數( IMyInterface<out T> )可能會讓你成為那里的一部分,但協方差會嚴​​格限制你在該接口中可以做的事情 - 協變類型T只能用於函數結果,永遠不能用於參數或可設置的屬性。

IList<T>未被聲明為協變的簡單事實不是意外或疏忽 - 它不能是協變的。 為了有用IList<T>需要添加(T項)和刪除(T項)等方法,當T是協變時,這些方法是禁止的。

暫無
暫無

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

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