C# .NET Casting 通用列表
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/674715/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
.NET Casting Generic List
提问by Josh
Can someone explain to me why in .NET 2.0 if I have an interface, IPackable
and a class that implements that interface OrderItem
, when I have a method that takes in a List<IPackable>
, passing in a list of List<OrderItem>
does not work?
有人可以向我解释为什么在 .NET 2.0 中,如果我有一个接口IPackable
和一个实现该接口的类OrderItem
,当我有一个接受 a 的方法时List<IPackable>
,传入的列表List<OrderItem>
不起作用?
Does anyone know how I could accomplish this functionality?
有谁知道我如何完成这个功能?
Code:
代码:
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;
}
}
The following code does not work.
以下代码不起作用。
List<OrderItem> orderItems = new List<OrderItem>();
List<IShipMethod> shipMethods = GetForShipWeight(orderItems);
采纳答案by JMD
The feature is called covariance/contravariance and will be supported in c# 4.0. You can read about it here: http://blogs.msdn.com/ericlippert/archive/tags/Covariance+and+Contravariance/default.aspx
该功能称为协方差/逆变,将在 c# 4.0 中得到支持。您可以在这里阅读:http: //blogs.msdn.com/ericlippert/archive/tags/Covariance+and+Contravariance/default.aspx
回答by mqp
JMD's answer is correct. For a workaround, you can try this:
JMD 的回答是正确的。对于解决方法,您可以尝试以下操作:
List<IPackable> orderItems = new List<IPackable>();
List<IShipMethod> shipMethods = GetForShipWeight(orderItems);
Or, if the list must be strongly typed as OrderItems, then this (3.0 only, sorry):
或者,如果列表必须强类型为 OrderItems,那么这个(仅限 3.0,抱歉):
List<IShipMethod> shipMethods =
GetForShipWeight(orderItems.Cast<IPackable>().ToList());
回答by mqp
JMD is half correct. In fact, it's absolutely incorrect to say that we will be able to cast a generic list with C# 4.0. It's true that covariance and contravariance will be supported in C# 4.0 but it will only works with interface and delegate and there will have a lot of constraints. Therefore, it won't work with List
.
JMD 对了一半。事实上,说我们将能够使用 C# 4.0 转换泛型列表是绝对不正确的。C# 4.0 确实支持协变和逆变,但它只适用于接口和委托,并且会有很多约束。因此,它不适用于List
.
The reason is really simple.
原因其实很简单。
If B is a subclass of A, we cannot say that List<B>
is a subclass of List<A>
.
如果 B 是 A 的子类,我们不能说它List<B>
是 的子类List<A>
。
And here's why.
这就是原因。
List<A>
exposes some covariances methods (returning a value) and some contravariances methods (accepting a value as a parameter).
List<A>
公开一些协方差方法(返回一个值)和一些逆变方法(接受一个值作为参数)。
e.g.
例如
List<A>
exposesAdd(A);
List<B>
exposesAdd(B);
List<A>
暴露Add(A);
List<B>
暴露Add(B);
If List<B>
inherits from List<A>
...than you would be able to do List<B>.Add(A);
如果List<B>
继承自List<A>
...比你能做的List<B>.Add(A);
Therefore, you would loose all type safety of generics.
因此,您将失去泛型的所有类型安全性。
回答by Zarigani
Actually, you can solve this by making GetForShipWeight a generic function:
实际上,您可以通过将 GetForShipWeight 设为通用函数来解决此问题:
public interface IPackable { double Weight { get; } }
public interface IShipMethod { }
public class OrderItem : IPackable { }
public List<IShipMethod> GetForShipWeight<T>(List<T> packages) where T : IPackable
{
List<IShipMethod> ship = new List<IShipMethod>();
foreach (IPackable package in packages)
{
// Do something with packages to determine list of shipping methods
}
return ship;
}
public void Test()
{
List<OrderItem> orderItems = new List<OrderItem>();
// Now compiles...
List<IShipMethod> shipMethods = GetForShipWeight(orderItems);
}
回答by Bigjim
An alternative solution that also works for .NET 3.5
也适用于 .NET 3.5 的替代解决方案
List<IShipMethod> shipMethods = GetForShipWeight(orderItems).ConvertAll(sm => sm as IShipMethod);