【问题标题】:Type compatibility and LINQ mystery类型兼容性和 LINQ 之谜
【发布时间】:2011-09-01 08:58:33
【问题描述】:

我有一段代码:

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

它不会编译,因为它需要一个演员表。如果我添加演员表,它会在运行时失败。

有没有什么方法可以在不复制结果列表的情况下对其进行编码?

【问题讨论】:

    标签: c# linq type-conversion


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

      • 这仍然是创建一个副本,它只是将复制操作移动到 .NET 运行时库中。
      【解决方案3】:

      啊哈,列表 vs 枚举!

      但是,它正在创建一个列表和 将其添加到空列表中

      不,它不是在创建一个列表 - 否则你的最后一行会起作用。它将IEnumerable 添加到列表中。

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

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

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

      然而,使用枚举时,项目是从底层集合中延迟检索的,并且仅在需要时才检索。因此,您可以对集合中由 where 子句过滤的项目进行枚举,然后更改所有值以使没有一个与过滤器匹配,当您从枚举中检索时,它将为空。

      【讨论】:

      • 现在我明白了——AddRange 调用可以接受枚举和列表。
      • @Loren - 是的,在您的代码中,您添加的是枚举,而不是列表。
      猜你喜欢
      • 1970-01-01
      • 2020-02-10
      • 1970-01-01
      • 2018-07-29
      • 2012-10-11
      • 2019-09-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多