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中不存在。否则那就太好了。