如果您有一个接口IFoo和一个类Bar : IFoo,为什么可以执行以下操作:
List<IFoo> foo = new List<IFoo>();
foo.Add(new Bar());
Run Code Online (Sandbox Code Playgroud)
但你做不到:
List<IFoo> foo = new List<Bar>();
Run Code Online (Sandbox Code Playgroud)
Ada*_*son 119
随便看一眼,这应该(如在啤酒应该是免费的)工作.但是,快速的健全检查会告诉我们为什么不能这样做.请记住,以下代码将无法编译.它旨在说明为什么它不被允许,即使它直到某一点看起来还不错.
public interface IFoo { }
public class Bar : IFoo { }
public class Zed : IFoo { }
//.....
List<IFoo> myList = new List<Bar>(); // makes sense so far
myList.Add(new Bar()); // OK, since Bar implements IFoo
myList.Add(new Zed()); // aaah! Now we see why.
//.....
Run Code Online (Sandbox Code Playgroud)
myList是一个List<IFoo>,意思是它可以采取任何实例IFoo.但是,这与它被实例化为的事实相冲突List<Bar>.由于List<IFoo>我有一个可以添加新实例的方法Zed,我们不能允许,因为底层列表实际上是List<Bar>无法容纳的Zed.
Dus*_*ell 39
原因是C#不支持C#3.0或更早版本中泛型的共同和逆变.这是在C#4.0中实现的,因此您将能够执行以下操作:
IEnumerable<IFoo> foo = new List<Bar>();
Run Code Online (Sandbox Code Playgroud)
请注意,在C#4.0中,您可以强制转换为IEnumerable <IFoo>,但是您无法转换为List <IFoo>.原因是由于类型安全,如果您能够将List <Bar>转换为List <IFoo>,您将能够将其他IFoo实现者添加到列表中,从而破坏类型安全性.
有关C#中协方差和逆变的更多背景知识,Eric Lippert有一个很好的博客系列.
小智 10
如果需要将列表转换为基类或接口的列表,可以执行以下操作:
using System.Linq;
---
List<Bar> bar = new List<Bar>();
bar.add(new Bar());
List<IFoo> foo = bar.OfType<IFoo>().ToList<IFoo>();
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
47385 次 |
| 最近记录: |