如何将List <object>转换为List <something else> </something> </object>

时间:2012-01-19 21:19:36

标签: c# generics

如何将List<object>投射到List<SomethingElse>

其中SomethingElse已知来自object


Bonus Chatter

投射名单:

List<Object> first = ...;

List<SomethingElse> second = (List<SomethingElse>)first;

不起作用:

  

无法将'System.Collections.Generic.List'类型转换为'System.Collections.Generic.List'

投射名单:

List<SomethingElse> second = first.Cast<SomethingElse>();

不起作用:

  

不能将类型'System.Collections.Generic.List'隐式转换为'System.Collections.Generic.List'

我实际上并不需要完整的List<T>对象,只需要ICollection<T>即可:

ICollection<SomethingElse> second = first;
ICollection<SomethingElse> second = (ICollection<SomethingElse>)first;
ICollection<SomethingElse> second = first.Cast<SomethingElse>();

不起作用。

3 个答案:

答案 0 :(得分:36)

LINQ,通过Enumerable类中的扩展方法实现,依赖于延迟执行:

  

在枚举查询对象之前,返回值序列的查询中使用的方法不会使用目标数据。这称为延迟执行。

Cast<T>不会立即创建新列表,而是存储执行操作所需的所有信息。该列表仅在需要时才会被枚举(例如,通过foreach语句)。

在您的情况下,如果您只是想迭代序列,您应该考虑坚持IEnumerable<T>接口,这是Cast<T>的声明返回类型:

IEnumerable<SomethingElse> second = first.Cast<SomethingElse>();
foreach (SomethingElse se in second)
{
    // ...
}

这是有效的,因为它只会在每个项目被迭代时执行强制转换。

如果您确信要立即创建新列表,请使用ToList

List<SomethingElse> second = first.Cast<SomethingElse>().ToList();

修改:回复评论中发布的点:

这取决于“可以修改的列表”的含义。有几个LINQ查询运算符允许您进一步更改查询的定义。例如,如果您要删除SomethingElse属性为IsDeleted的所有true元素,则可以使用Where运算符:

IEnumerable<SomethingElse> second = first.Cast<SomethingElse>();
second = second.Where(element => !element.IsDeleted);

如果要添加一系列新元素,可以使用Concat运算符:

second = second.Concat(anotherCollectionOfSomethingElse);

如果您想按ID的升序排序序列,请使用OrderBy运算符:

second = second.OrderBy(element => element.ID);

每次,我们都会在查询的前一个定义上应用查询运算符,并将新的(复合)查询分配给我们的second变量。 LINQ会将所有运算符存储在查询定义中。然后,当实际枚举序列时(例如,通过foreachToList),它将为您提供序列的复合结果,并按顺序应用所有查询运算符。

与延迟执行/延迟评估的所有情况一样,请注意不要过度使用此功能。例如,如果你要应用一个Where运算符来大幅减少序列的大小,那么急切地执行查询并存储枚举列表可能是有意义的。

答案 1 :(得分:17)

我认为你接近Cast<T>表达式。区别在于Cast<T>返回IEnumerable<T>,而不是List<T>

试试这个:

IEnumerable<SomethingElse> second = first.Cast<SomethingElse>();

您可以通过执行类似操作来获取列表:

List<SomethingElse> second = first.Cast<SomethingElse>().ToList();

答案 2 :(得分:15)

您可以选择使用CastOfType。如果无法转换为指定的类型,Cast将抛出异常。另一方面,OfType将仅返回列表中可以强制转换为指定类型的项目。我建议在你的情况下使用OfType

List<Foo> fooList = myList.OfType<Foo>().ToList();