IList <iwhatever>作为方法参数</iwhatever>

时间:2009-08-01 06:28:43

标签: c# generics interface

我有两个IList<ICat>,我正在尝试创建一个方法,它接受IList<ICat>并做一些工作。我在尝试向其IList<PussyCat>IList<OtherCat>传递时遇到问题,PussyCatOtherCat实施ICat

我试过了:

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

只是

DoWork(cats);

但是没有编译。有什么想法吗?

4 个答案:

答案 0 :(得分: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[]的方法。

答案 1 :(得分: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);
    }
    

答案 2 :(得分:1)

如果该方法不需要直接索引(IList<T>)并且不需要添加/删除项目(ICollection<T>),则传递IEnumerable<T>Cast<T>()扩展程序允许将任何IList [insert ICat - 派生类型]转换为IEnumerable<ICat>

答案 3 :(得分:0)

直到C#4.0到达,它支持co和contra方差,你可能会得到这样的东西:

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>);