类型兼容性和LINQ之谜

时间:2011-05-25 00:16:23

标签: c# linq type-conversion

我有一段代码:

List<OneFeat> Feats;
...
List<OneFeat> Results = new List<OneFeat>(0);
foreach (OneFeat Test in Feats)
    if (String.Compare(Test.Name, Target, true) == 0)
        Results.Add(Test);
return Results;

Resharper提供:

List<OneFeat> Results = new List<OneFeat>(0);
Results.AddRange(Feats.Where(Feat => String.Compare(Feat.Name, Target, true) == 0));
return Results;

当然有效。但是,它正在创建一个列表并将其添加到空列表中,因此我尝试将其简化为:

return Feats.Where(Feat => String.Compare(Feat.Name, Target, true) == 0));

哪个不会编译,因为它想要一个演员。如果我添加了强制转换,它会在运行时失败。

有没有办法在不复制结果列表的情况下对此进行编码?

3 个答案:

答案 0 :(得分:3)

Aha,Lists vs Enumerations!

  

然而,它正在创建一个列表和   将其添加到空列表

不,它没有创建列表 - 否则你的最后一行会起作用。它正在为列表添加IEnumerable

Where运算符返回IEnumerable,它不是“列表” - 它更像是一个松散,可迭代和非具体的集合。

当您调用AddRange时,将迭代此集合并将其添加到空列表中。我希望这与简单地在结果上调用ToList非常相似。

这个概念起初有点难以理解,但将IEnumerable视为返回数据而不是数据集合的函数。如果您创建了由where子句筛选的项目列表,然后更改这些项目的值,则列表不会更改 - 它已经创建,并且不会根据这些值删除或添加项目(除非您明确地这样做)。

但是,使用枚举,只有在需要时才会懒惰地从基础集合中检索项目。因此,您可以对集合中的where子句进行过滤的项进行枚举,然后更改所有值,使其不与过滤器匹配,并且从枚举中检索时它将为空。

答案 1 :(得分:1)

如果您只想枚举匹配的Feats列表,请将返回类型更改为IEnumerable<OneFeat>。如果必须返回实际列表,则必须复制它,因为原始Feats对象不代表与Test.Name匹配的专长子集。

答案 2 :(得分:1)

或者您可以在Where语句的末尾添加.ToList(),如下所示:

return Feats.Where(Feat => String.Compare(Feat.Name, Target, true) == 0)).ToList();