我知道可以将一列项目从一种类型强制转换为另一种类型(假设你的对象有一个公共静态显式操作符方法来执行强制转换),如下所示:

List<Y> ListOfY = new List<Y>();

foreach(X x in ListOfX)
    ListOfY.Add((Y)x);

但是是否可以一次强制施放整个列表?例如,

ListOfY = (List<Y>)ListOfX;

当前回答

dynamic data = List<x> val;  
List<y> val2 = ((IEnumerable)data).Cast<y>().ToList();

其他回答

如果X起源于Y,你也可以使用ToList<T>方法而不是Cast<T>方法

listOfX.ToList<Y>()

直接强制转换变量ListOfY = (List<Y>)ListOfX是不可能的,因为它需要List<T>类型的co/逆变,并且在每种情况下都不能保证。请继续阅读,看看这个铸造问题的解决方案。

虽然能够编写这样的代码看起来很正常:

List<Animal> animals = (List<Animal>) mammalList;

因为我们可以保证每个哺乳动物都是动物,这显然是一个错误:

List<Mammal> mammals = (List<Mammal>) animalList;

因为不是每一种动物都是哺乳动物。

但是,使用c# 3及以上版本,您可以使用

IEnumerable<Animal> animals = mammalList.Cast<Animal>();

这让选角变得容易一些。这在语法上等同于逐个添加代码,因为它使用显式强制转换将列表中的每个哺乳动物强制转换为一个Animal,如果强制转换不成功,则会失败。

如果您希望对强制转换/转换过程有更多的控制,可以使用List<T>类的ConvertAll方法,该方法可以使用提供的表达式来转换项。它还有一个额外的好处,它返回一个List,而不是IEnumerable,所以不需要. tolist()。

List<object> o = new List<object>();
o.Add("one");
o.Add("two");
o.Add(3);

IEnumerable<string> s1 = o.Cast<string>(); //fails on the 3rd item
List<string> s2 = o.ConvertAll(x => x.ToString()); //succeeds

如果X真的可以转换为Y,你应该能够使用

List<Y> listOfY = listOfX.Cast<Y>().ToList();

一些需要注意的事情(H/T评论者!)

你必须包括使用System.Linq;来获得这个扩展方法 这将强制转换列表中的每个项——而不是列表本身。调用ToList()将创建一个新的List<Y>。 此方法不支持自定义转换运算符。(参见为什么Linq强制转换<> helper不能与隐式强制转换操作符一起工作?) 此方法不适用于具有显式操作符方法的对象(framework 4.0)

您可以使用List<Y>。ConvertAll<T>([从Y到T的转换器]);

这不是这个问题的答案,但它可能对一些人有用:正如@SWeko所说,由于协方差和逆变性,List<X>不能在List<Y>中强制转换,但List<X>可以强制转换为IEnumerable<Y>,甚至使用隐式强制转换。

例子:

List<Y> ListOfY = new List<Y>();
List<X> ListOfX = (List<X>)ListOfY; // Compile error

but

List<Y> ListOfY = new List<Y>();
IEnumerable<X> EnumerableOfX = ListOfY;  // No issue

最大的优点是它不会在内存中创建一个新的列表。