从List <mytype>到IEnumerable <mytype>返回List <mytype>的转换无效,为什么?</mytype> </mytype> </mytype>

时间:2012-07-29 16:11:02

标签: c# .net linq ienumerable

基本上我有这种方法。

public List<Customer> FilterCustomersByStatus(List<Customer> source, string status)
{
    return (List<Customer>)source.Where(c => c.Status == status);
}

我向我抛出了一个无法施放的错误:

  

无法将'WhereListIterator`1 [AppDataAcces.Customer]'类型的对象强制转换为'System.Collections.Generic.List`1 [AppDataAcces.Customer]'。

为什么......?由于底层类型是相同的,Enumerable.Where是否创建了WhereListIterator的新实例,如果是这样,为什么有人会这样做,因为这是不必要的性能和功能损失,因为我总是要创建一个新列表(.ToList( ))

5 个答案:

答案 0 :(得分:10)

  

是Enumerable.Where创建WhereListIterator

的新实例

  

如果是这样,为什么有人会这样做

因为它允许延迟流式传输行为。如果消费者只想要第一个或第二个条目,Where将不必过滤所有列表。这对LINQ来说是正常的。

  

因为这是不必要的性能和功能损失,因为我总是要创建一个新列表(.ToList())

“性能和功能的损失”来自您的设计。过滤后您不需要List<Customer>,因为对它进行任何修改都没有意义。

更新:“为什么会这样实施” 因为它是在IEnumerable上实施的,而不是IList。因此它看起来像IEnumerable,它像IEnumerable一样嘎嘎作响。

此外,以这种方式实现它要容易得多。想象一下你必须在Where上写IList。哪个必须返回IList。它该怎么办?在原始列表上返回代理?每次访问都会遭受巨大的性能损失。返回包含已过滤商品的新列表?这与做Where().ToList()一样。返回原始列表但删除了所有不匹配的项目?这就是RemoveAll的用途,为什么要制作另一种方法。

请记住,LINQ尝试播放功能,并尝试将对象视为不可变的。

答案 1 :(得分:2)

正如其他人所指出,您需要使用ToList将结果转换为List<T>

原因是Where被延迟评估,因此Where 它的作用是创建一个IEnumerable,根据需要过滤数据。

懒惰评估有几个好处。它可能更快,允许Where使用无限IEnumerable秒等

ToList强制将结果转换为List<T>,这似乎就是您想要的。

答案 2 :(得分:0)

Where扩展名过滤并返回IEnumerable<TSource>因此您需要调用.ToList()将其转换回来

public List<Customer> FilterCustomersByStatus(List<Customer> source, string status)
{
    return source.Where(c => c.Status == status).ToList();//This will return a list of type customer
}

答案 3 :(得分:0)

IEnumerable和IList之间的区别在于,可枚举不包含任何数据,它包含一个iterator,当您请求新数据时它会通过数据(例如,使用foreach循环)。另一方面,列表是数据的副本。在您的情况下,要创建List,ToList()方法将遍历整个数据并将它们添加到List对象。

根据您计划的用途,两者都有优点和缺点。例如,如果您计划多次使用整个数据,则应该使用该列表,但如果您计划使用它一次或计划使用linq再次查询,则应该选择enumerable。 / p>

编辑: 问题的答案为什么返回类型Where WhereListIterator而不是List,这部分是因为Linq如何工作。例如,如果您在第一个之后有另一个Where或另一个Linq语句,则编译器将使用整个方法链创建单个查询,然后返回最终查询的迭代器。另一方面,如果第一个Where将返回一个List,它将导致链中的每个Linq方法分别对数据执行。

答案 4 :(得分:-1)

试试这个:

public List<Customer> FilterCustomersByStatus(List<Customer> source, string status)
{
    return source.Where(c => c.Status == status).ToList();
}