C#2.0中的接口多态性

C#2.0中的接口多态性,c#,.net,oop,interface,.net-2.0,C#,.net,Oop,Interface,.net 2.0,假设我有这个界面: public interface IFoo { string Text {get;} } 这个实现它的类: public class Bar : IFoo { public string Text { get {return "Hello World!";} } } 我有一个函数,它将列表作为参数。当我尝试向其传递列表时,我得到以下编译器错误: Argument 1: cannot convert from System.Collect

假设我有这个界面:

public interface IFoo
{
   string Text {get;}
}
这个实现它的类:

public class Bar : IFoo
{
   public string Text
   {
      get {return "Hello World!";}
   }
}
我有一个函数,它将
列表
作为参数。当我尝试向其传递
列表时,我得到以下编译器错误:

Argument 1: cannot convert from System.Collections.Generic.List<Bar>
to System.Collections.Generic.List<IFoo>
参数1:无法从System.Collections.Generic.List转换
到System.Collections.Generic.List
为什么会这样?这似乎与我直接传递从
Bar
继承的类列表的原因相同

为什么会这样?这似乎与我传递一个直接从Bar继承的类列表的原因相同

因为这场灾难可能发生:

class EvilBar : IFoo { }

List<Bar> list = new List<Bar>();
List<IFoo> foos = list; // suppose it were allowed
foos.Add(new EvilBar());
class:IFoo{}
列表=新列表();
List foos=List;//如果允许的话
添加(新的EvilBar());
现在,您已经将一个
Bar
添加到一个列表中,而该列表只能接受
Bar
。哎呀


基本上,您已经发现,
T->List
T
中不是协变的,因为.NET2.0中不支持泛型逆变。不过,您可以使用数组来实现

IFoo[] foos = new Bar[5];
另一个选择是这样做

List<IFoo> myList = myBarList.ConvertAll(b => (IFoo)b);
List myList=myBarList.ConvertAll(b=>(IFoo)b);
不要通过
列表
。使用“强制转换”并传递以下内容:

yourObj.YourMethod(yourListOfBar.Cast<IBar>().ToList());
yourObj.YourMethod(yourListOfBar.Cast().ToList());

但这似乎不是问题。编译器允许从
List
转换到
List
,因为
Bar
实现了
IFoo
。出于同样的原因,它应该允许在实现
IFoo
的对象列表中添加
EvilBar
。但是,它不应该允许从
列表
回溯到
列表。在.NET的更高版本中,这是否有所改变?@linepogl:你在说什么<代码>IFoo foo=new evillbar()非常好。你投了反对票吗?@linepogl:这不是一个直接的类比。您不能将
列表添加到
列表中,这就是为什么我的示例是一个灾难。@linepogl我想您缺少的是
列表和
foos
仍然是同一个列表。例如,当您使用.NET 3.5扩展方法
Cast
时,它正在创建一个新列表,在这种情况下,可以向
列表添加任何内容
,但在这种情况下,由于它们都是相同的列表,将
EvilBar
添加到
foos
表面上看起来很好,但实际上它仍然是一个不好的
列表
。这种协方差被破坏了,实际上是因为我在回答中概述的原因。我将参数转换为数组,在传递的参数末尾添加了
.ToArray()
,编译器很高兴。@Jefferson先生:这不安全@杰斐逊先生:是的,你可能会遇到运行时错误。尝试使用泛型。然后,您的函数可以将List作为参数。签出向下滚动到通用方法的一半我需要传递的对象来实现这个接口。如果我使用的是较新版本的.NET,我会很乐意使用泛型并使用
Func
参数从我传递的对象中获取所需的信息。根据我在.NET 2.0中链接泛型应该工作的文章,您可以使用
Frob(列表),其中T:IFoo
。我认为您的
Cast
方法在.NET 2.0中不存在。否则那就太好了。