2011-12-12 14 views
1

有人可以解釋爲什麼下面的代碼會引發以下異常:將一個集合<T>投射到一個界面 - 爲什麼它不工作?

InvalidCastException: Unable to cast object of type 'System.Collections.ObjectModel.Collection'1[UserQuery+Test]' to type 'System.Collections.ObjectModel.Collection'1[UserQuery+ITest]'.

public interface ITest 
{ 
} 

public class Test : ITest 
{ 
} 

void Main() 
{ 
    Collection<Test> t = new Collection<Test>(); 
    t.Add(new UserQuery.Test()); 
    var casted = (Collection<ITest>)t.Cast<ITest>(); 
} 

的簽名Cast<T>意味着T輸出,但事實並非如此。到底是怎麼回事? covariance與它有什麼關係?

回答

6

當您使用Enumerable.Cast<T>時,您將創建新的IEnumerable<T>,而不僅僅是傳統意義上的演員陣容。

因此,返回的集合不再是Collection<T>,而是IEnumerable<ITest>的內部(非公共)實現。

+0

嗯,這可能會或可能不會創建一個新的'的IEnumerable '。如果不需要,它會進行優化。見http://msmvps.com/blogs/jon_skeet/archive/2011/01/13/reimplementing-linq-to-objects-part-33-cast-and-oftype.aspx –

+0

@JonSkeet非常真實 - 但它更安全假設它不會與你傳遞的同一個集合類型... –

+1

假設可能發生 - 對結果的操作可能會影響源或不是,所以無論哪種方式對壞的假設都有危險是比較安全的。 –

1

鑄造是不必要的。 您可以創建一個集合,所以你不需要投:

void Main() 
{ 
    Collection<ITest> t = new Collection<ITest>(); 
    t.Add(new UserQuery.Test()); 
} 
相關問題