我记得看到了很多周围的信息在网络上这个问题之前,让我不知道我的答案是否真的会添加新的东西,但我会尝试。
如果您使用.NET 4,请注意IEnumerable(Of T)的定义实际上是IEnumerable(Of Out T)。新的Out关键字已在版本4中引入,它指示此接口的协方差。然而,List(Of T)类仅被定义为List(Of T)。 Out关键字在这里没有使用,所以这个类不是协变的。
我会提供一些例子来试图解释为什么某些作业如你所描述的作业不能完成。我发现你的问题是用VB编写的,所以我很抱歉使用C#。
假设您有以下类:
abstract class Vehicle
{
public abstract void Travel();
}
class Car : Vehicle
{
public override void Travel()
{
// specific implementation for Car
}
}
class Plane : Vehicle
{
public override void Travel()
{
// specific implementation for Plane
}
}
您可以创建汽车的名单,只能包含对象从汽车衍生:
List<Car> cars = new List<Car>();
您还可以创建列表飞机,只能包含对象从飞机衍生:
List<Plane> planes = new List<Plane>();
你甚至可以创建一个列表汽车,其中可以包含车辆派生的任何对象:
List<Vehicle> vehicles = new List<Vehicle>();
是合法的汽车添加到汽车的名单,这是合法的飞机添加到面的清单。将汽车和飞机添加到车辆列表中也是合法的。因此,所有下面的代码行是有效的:
cars.Add(new Car()); // add a car to the list of cars
planes.Add(new Plane()); // add a plane to the list of planes
vehicles.Add(new Plane()); // add a plane to the list of vehicles
vehicles.Add(new Car()); // add a car to the list of vehicles
这是不合法的汽车添加到面的清单,也不是合法的飞机加入到汽车的列表。下面的代码行不会编译:
cars.Add(new Plane()); // can't add a plane to the list of cars
planes.Add(new Car()); // can't add a car to the list of planes
因此,这是不合法的,试图通过赋予汽车的列表或飞机到车辆变量列表来绕过这个限制:
vehicles = cars; // This is not allowed
vehicles.Add(new Plane()); // because then you could do this
考虑上面两行代码的含义。这就是说车辆变量实际上是一个List<Car>
对象,它应该只包含从Car派生的对象。但是,因为List<Vehicle>
包含添加(车辆)方法,所以理论上可以将一个平面对象添加到List<Car>
集合,这肯定是不正确的。
但是,将变量指定为汽车列表或飞机列表是完全有效的。
IEnumerable<Vehicle> vehicles = cars;
foreach (Vehicle vehicle in vehicles)
{
vehicle.Travel();
}
这里的快速解释是IEnumerable接口不允许您操作集合。它本质上是一个只读接口。 T对象(本例中为车辆)仅作为IEnumerable接口的Current属性的返回值公开。没有方法将Vehicle对象作为输入参数,因此不会以非法的方式修改集合。
边注意:我一直认为IList<T>
接口是一个IReadableList<out T>
接口和IWritableList<in T>
接口的复合接口。
http://blogs.msdn.com/b/ericlippert/archive/tags/covariance+and+contravariance/ – Oded 2011-12-19 18:37:44
我已阅读了几篇文章,其中没有一篇帮助我回答这个特定的实例。你能指出特定的文章或其中的一部分,它涵盖了为什么我可以直接从特定类型的列表到界面列表? – Jay 2011-12-19 18:53:51
http://blogs.msdn.com/b/ericlippert/archive/2007/10/26/covariance-and-contravariance-in-c-part-five-interface-variance.aspx – Oded 2011-12-19 19:10:58