2012-11-12 27 views
4

在下面的示例中,爲什麼我不能將collectionA轉換爲collectionB,前提是編譯器知道TItemA<T>通用集合之間的對應關係

public class A<T> 
{ 
} 

public void Foo<TItem, T>() where TItem : A<T> 
{ 
    var collectionA = new List<TItem>(); 
    var collectionB = (List<A<T>>)collectionA; // "Cannot cast" error here 
} 
+4

搜索「協方差」和「逆變」 – Mehrdad

+0

爲什麼你首先將它設爲通用?如果TItem始終爲A

+2

查看有關協方差和逆變的此FAQ。 http://blogs.msdn.com/b/csharpfaq/archive/2010/02/16/covariance-and-contravariance-faq.aspx –

回答

1

的問題是,它將使你不合適的物品放入collectionA。

下面是它的一個簡單改造,這有望使得它更容易看到問題:

假設你有(僞):

class Animal {...} 

class Dog: Animal { Bark(){} } 

class Cat: Animal { Meow(){} } 

現在想象一下,你可以這樣做:

var dogs = new List<Dog>(); 

dogs.Add(new Dog()); 

dogs[0].Bark(); 

var animals = (List<Animal>) dogs; 

然後你就可以這樣做:

animals.Add(new Animal()); // Adds an Animal to the list 'dogs', which 'animals' references. 

dogs[1].Bark(); // dogs will now have two elements, but the second isn't a dog - 
       // so calling Bark() will explode. 
+0

當然感謝你了。我有一些代碼味道,現在擺脫。 – hashlock

0

我相信這是因爲你指示系統從List<X>轉換爲List<Y>,而不是說你要在列表中投每個項目從XY

你可以這樣做,但:

public class A<T> 
{ 
} 

public void Foo<TItem, T>() where TItem : A<T> 
{ 
    var collectionA = new List<TItem>(); 
    var collectionB = new List<A<T>>(collectionA.ToArray()); 
} 
0

你要爲使用

var collectionB = collectionA.OfType<List<A<T>>>(); 

var collectionB = collectionA.Cast<List<A<T>>>(); 

第一個將忽略任何的List<A<T>>類型的不是,也不會被視爲它。如果列表中有某些內容無法轉換,則第二個會拋出異常。