我有这样的功能:
DoSomething(List<IMyInterface>)
IMyInterface是一个接口,MyClass是一个实现此接口的类 MyClass类:IMyInterface
我致电DoSomething(List<MyClass>)
,看起来它不起作用。
我怎样才能将类的列表作为函数的参数传递给类的接口列表?谢谢!
答案 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#中使用。