簡體   English   中英

為什么不能將一個受約束的開放泛型類型轉換為受約束類型?

[英]Why can't you cast a constrained open generic typed to the constrained type?

我想我一定遺漏了一些東西,為什么我不能編譯這個:

class Foo<T> where T : Bar
{
    T Bar;
}

abstract class Bar
{ }

class MyBar : Bar
{ }

static void Main(string[] args)
{
    var fooMyBar = new Foo<MyBar>();
    AddMoreFoos(fooMyBar);
}

static void AddMoreFoos<T>(Foo<T> FooToAdd) where T : Bar
{
    var listOfFoos = new List<Foo<Bar>>();
    listOfFoos.Add(FooToAdd); //Doesn't compile
    listOfFoos.Add((Foo<Bar>)FooToAdd); //doesn't compile
}

通過在此處使用列表,您會使事情變得比需要的更混亂......這樣最容易看到效果:

// This won't compile
Foo<Bar> fooBar = new Foo<MyBar>();

鑒於這無法編譯,因此您不能將Foo<MyBar>添加到List<Foo<Bar>>也就不足為奇了

那么為什么Foo<MyBar>不是Foo<Bar>呢? 因為泛型類不是協變的。

泛型變量僅在 C# 4 中引入 - 它僅適用於接口和委托。 所以你可以(在 C# 4 中)這樣做:

IEnumerable<MyBar> x = new List<MyBar>();
IEnumerable<Bar> y = x;

但你不能這樣做:

IList<MyBar> x = new List<MyBar>();
IList<Bar> y = x;

我有一個完整的關於方差的討論,您可以從NDC 2010 視頻網站下載 - 只需搜索“方差”。

它無法編譯,因為如果您要使用Foo<int>調用您的方法,那么該調用將失敗:您正試圖為泛型參數假定特定類型。

您需要使用var listOfFoos = new List<Foo<T>>()代替,然后Add應該可以工作。

(編輯:同樣,如果您使用Foo<T> ,演員也會起作用 - 但您仍然不能在您的代碼中假設TBar )。

暫無
暫無

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

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