2009-08-01 90 views
2

我有兩個IList<ICat>,我試圖創建一個方法,需要一個IList<ICat>並做一些工作。我在嘗試將IList<PussyCat>IList<OtherCat>傳遞給它時遇到了問題,PussyCatOtherCat都實現了ICatIList <IWhatever>作爲方法參數

我已經試過:

List<PussyCat> cats = ... 
DoWork((IList<ICat>)cats); 

,只是

DoWork(cats); 

但無論編譯。有任何想法嗎?

+0

請顯示您的Dowork()方法的簽名... – 2009-08-01 06:30:28

回答

7

C#泛型是不變的。這意味着List<string>不是List<object>

C#4.0引入了safe covariance/contravariance但仍然無法通過List<string>作爲List<object>。原因是:

List<string> x = new List<string>(); 
List<object> o = x; // assume this statement is valid 
o.Add(5); // Adding an integer to a list of strings. Unsafe. Will throw. 

另一方面,數組是協變的。您可以將string[]傳遞給期望object[]的方法。

+0

謝謝。我已經閱讀過關於共同和反對方差的內容,但我認爲需要更詳細的閱讀。我發現我需要越來越多的C#4.0。 – Echilon 2009-08-01 06:37:33

+3

請注意,如果`DoWork`只是`foreach`集合並且不改變任何內容,則可以聲明該參數爲`IEnumerable `,並用`DoWork(cats.Cast ())`調用它。 – 2009-08-01 06:40:09

0

直到C#4.0到達其對CO和反方的支持,你也許可以用這樣的閃避:

public void DoWork(IEnumerable<ICat> cats) 
{ 
    //do something 
} 
List<PussyCat> pussyCats = new List<PussyCat>; 
List<OtherCat> otherCats = new List<OtherCat>; 
DoWork(pussyCats.OfType<ICat>); 
DoWork(otherCats.OfType<ICat>); 
+1

正如我所說的,對於這種特定的情況,沒有什麼會改變C#4.0,'OfType`返回`IEnumerable`而不是`IList`。 – 2009-08-01 06:48:42

5

有兩個備選方案:

  1. 讓你的方法像這樣:

    public void DoWork<T> (IList<T> cats_) where T : ICat 
    { 
        //Do work; 
    } 
    
  2. 另一種可能性是有一個像

    public void DoWork(IList<ICat> cats_) 
    { 
        //Do work; 
    } 
    

    ,並調用它以下列方式:

    { 
        //....Assuming: IList<PussyCat> iListOfPussyCats 
        List<PussyCat> pussyCats = new List<PussyCats>(iListOfPussyCats); 
        DoWork(pussyCats.ConvertAll<ICat>(c => c as ICat); 
    } 
    
1

如果方法不真正需要直接索引(IList<T>),並且不需要添加/刪除項目(ICollection<T>) ,然後通過一個IEnumerable<T>Cast<T>()擴展方法允許將[插入ICat衍生類型]的任何IList作爲IEnumerable<ICat>傳遞。