2012-01-19 51 views
41

哪有我投了List<object>List<SomethingElse>如何投放列表<object>为List <SomethingElse>

其中SomethingElse被称为从object下降)


奖金看点

铸造名单:

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>(); 

不起作用。

+0

相关? http://stackoverflow.com/questions/1266014/c-sharp-casting-a-listobjbase-as-listobj – eldarerathis

+0

可能的重复http://stackoverflow.com/questions/7955890/how-to-cast-listclassb-to -listclassa-when-classb-inherits-from-classa – dash

+0

这个工作吗? List second = first.Select(o =>(SomethingElse)o).ToList(); – asmo

回答

31

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运算符,这会大大减少你的序列的大小,那么可能会急切地执行查询并存储枚举列表。

+0

我不需要立即创建一个新列表;但我确实需要一个可以修改的列表,并且不受协方差问题的限制。如果ToList是我需要的,那么我需要使用它。当然,我会更喜欢返回的'List'是'first'的一个包装,允许推迟执行。 –

13

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

试试这个:

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

你可以做类似的事情得到一个列表:

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

可以选择使用CastOfType的选项。如果你不能转换为指定的类型,那么Cast会抛出异常。另一方面,OfType将只返回列表中可以转换为指定类型的那些项目。我会建议在您的情况下使用OfType

List<Foo> fooList = myList.OfType<Foo>().ToList(); 
相关问题