.NET Casting通用列表

Jos*_*osh 6 .net c# generics casting

有人可以向我解释为什么在.NET 2.0中,如果我有一个接口,IPackable以及一个实现该接口的类OrderItem,当我有一个接受a的方法List<IPackable>,传入一个列表List<OrderItem>不起作用?

有谁知道我怎么能完成这个功能?

码:

public interface IPackable {
        double Weight{ get; }
}

public class OrderItem : IPackable


public List<IShipMethod> GetForShipWeight(List<IPackable> packages) {
   double totalWeight = 0;
   foreach (IPackable package in packages) {
        totalWeight += package.Weight;
   }
}
Run Code Online (Sandbox Code Playgroud)

以下代码不起作用.

List<OrderItem> orderItems = new List<OrderItem>();
List<IShipMethod> shipMethods = GetForShipWeight(orderItems);
Run Code Online (Sandbox Code Playgroud)

小智 14

JMD是正确的一半.事实上,说我们能够使用C#4.0转换通用列表是绝对不正确的.确实,C#4.0将支持协方差和逆变,但它只适用于接口和委托,并且会有很多约束.因此,它将无法使用List.

原因很简单.

如果B是A的子类,我们不能说它List<B>是A的子类List<A>.

这就是原因.

List<A> 公开一些协方差方法(返回值)和一些逆变方法(接受一个值作为参数).

例如

  • List<A> 自曝 Add(A);
  • List<B> 自曝 Add(B);

如果List<B>继承自List<A>...而不是你能做到的List<B>.Add(A);

因此,您将失去仿制药的所有类型安全性.


JMD*_*JMD 11

该功能称为协方差/逆变,将在c#4.0中得到支持.你可以在这里阅读:http://blogs.msdn.com/ericlippert/archive/tags/Covariance+and+Contravariance/default.aspx

  • 文章似乎已感动。在下面查看示例,Cast &lt;&gt;类位于System.Linq命名空间中,仅供参考。 (2认同)

mqp*_*mqp 7

JMD的答案是正确的.要解决此问题,您可以尝试这样做:

List<IPackable> orderItems = new List<IPackable>();
List<IShipMethod> shipMethods = GetForShipWeight(orderItems);
Run Code Online (Sandbox Code Playgroud)

或者,如果列表必须强类型为OrderItems,那么这个(仅限3.0,抱歉):

List<IShipMethod> shipMethods =
    GetForShipWeight(orderItems.Cast<IPackable>().ToList());
Run Code Online (Sandbox Code Playgroud)


Big*_*jim 5

也适用于 .NET 3.5 的替代解决方案

List<IShipMethod> shipMethods = GetForShipWeight(orderItems).ConvertAll(sm => sm as IShipMethod);
Run Code Online (Sandbox Code Playgroud)