我記得看到了很多周圍的信息在網絡上這個問題之前,讓我不知道我的答案是否真的會添加新的東西,但我會嘗試。
如果您使用.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