我的理解是,如果S
是一个子类的T
,那么List
是不是一个孩子List
.精细.但是接口有不同的范例:如果是Foo
实现IFoo
,那么为什么List
不是(一个例子)List
?
因为可能没有实际的类IFoo
,这是否意味着我在暴露a时总是必须强制转换列表中的每个元素List
?或者这只是糟糕的设计,我必须定义自己的集合类ListOfIFoos
才能与它们一起工作?对我来说似乎都不合理......
考虑到我正在尝试编程接口,那么暴露这样一个列表的最佳方式是什么?我目前正倾向于实际存储我的List
内部作为List
.
您List
不是子类,List
因为您无法MyOwnFoo
在其中存储对象,这也恰好是一个IFoo
实现.(利斯科夫替代原则)
存储List
而不是专用的想法List
是可以的.如果您需要将列表的内容强制转换为其实现类型,这可能意味着您的界面不合适.
这是一个为什么你不能这样做的例子:
// Suppose we could do this... public ListGetDisposables() { return new List (); } // Then we could do this List disposables = GetDisposables(); disposables.Add(new Form());
此时,为了保存MemoryStreams而创建的列表现在有一个Form.坏!
基本上,这种限制是为了保持类型安全.在C#4和.NET 4.0中,对此的支持有限(称为方差),但由于上面给出的原因,它仍然不支持这种特定情况.
在返回的函数中,您必须使列表成为接口列表,并在创建对象时将其作为实现它的对象.像这样:
function ListgetList() { List r = new List (); for(int i=0;i<100;i++) r.Add(new Foo(i+15)); return r; }
大规模编辑
你将能够用C#4.0做到这一点,但 [感谢Jon]
你可以使用ConvertAll
以下方法解决它:
public ListIFoos() { var x = new List (); //Foo implements IFoo /* .. */ return x.ConvertAll (f => f); //thanks Marc }