如何将类列表传递给接口列表?

时间:2011-10-03 02:19:27

标签: c# class list interface

我有这样的功能:

DoSomething(List<IMyInterface>)

IMyInterface是一个接口,MyClass是一个实现此接口的类 MyClass类:IMyInterface

我致电DoSomething(List<MyClass>),看起来它不起作用。 我怎样才能将类的列表作为函数的参数传递给类的接口列表?谢谢!

3 个答案:

答案 0 :(得分:34)

如果您的代码只是迭代方法内的序列(不是通过索引添加,删除或访问),请将您的方法更改为以下之一

DoSomething(IEnumerable<IMyInterface> sequence)
DoSomething<T>(IEnumerable<T> sequence) where T : IMyInterface

IEnumerable<>接口是协变的(从.NET 4开始)(第一个选项)。或者如果使用C#3,您可以使用后一个签名。

否则,如果您需要索引操作,请在传递之前转换列表。在调用中,您可能有

// invocation using existing method signature 
DoSomething(yourList.Cast<IMyInterface>().ToList());

// or updating method signature to make it generic
DoSomething<T>(IList<T> list) where T : IMyInterface

后一个签名允许您做的是还支持添加或删除列表(在调用点可见),并且它还允许您在不先复制它的情况下使用该列表。

即便如此,如果您只是循环遍历列表,我会赞成加入IEnumerable<>的方法。

答案 1 :(得分:13)

这一般不安全,因为列表是可变的。假设您将List<MyClass>的引用传递给List<IMyInterface>,那么他们会:

void Foo(List<IMyInterface> list)
{
    IMyInterface x = new MyOtherClassWhichAlsoImplementsIMyInterface();
    list.Add(x);
}

现在,您的List<MyClass>包含的课程实例不是MyClass。这会违反类型安全。 (正如其他答案所述,您可以通过仅传递List的IEnumerable<>接口来避免此问题,该接口提供只读访问权限,因此是安全的。)

有关详细信息,请参阅Using Variance in Interfaces for Generic Collections on MSDN。另请参阅a good summary of covariance and contravariance and various C# features that support it

答案 2 :(得分:1)

如果您只需要浏览列表,请使用IEnumerable声明该方法。如果要向列表中添加元素,那么您所要求的不是类型安全的,因此可能不允许在C#中使用。