【问题标题】:Replace foreach loop with linq用 linq 替换 foreach 循环
【发布时间】:2013-07-08 11:24:54
【问题描述】:

我尝试替换代码

foreach (var discovery in mpwrapper.parser.Discoveries)
{
   solution.AddFile("Discoveries", discovery.DisplayStringName + ".mpx", discovery);
}

使用以下 linq 表达式

mpwrapper.parser.Discoveries.Select(
                    s => solution.AddFile("Discoveries", s.DisplayStringName + ".mpx", s));

但出现错误

方法的类型参数 'System.Linq.Enumerable.Select(System.Collections.Generic.IEnumerable, System.Func)' 不能从用法中推断出来。尝试 明确指定类型参数。

如何将此 foreach 循环转换为我对 IEnumerable 集合中的每个对象执行方法的 linq 查询?

【问题讨论】:

  • 我猜你的 solution.AddFile 方法没有返回任何东西 - 这是正确的吗?
  • Select 执行有副作用的代码是使用不当。只需执行foreach。或者List<T>.ForEach(),这是一种预期会产生副作用的方法(= 方法外的状态变化)。
  • 顺便说一句,将foreach 循环更改为Linq 只是为了它,这是我在.NET 中知道的使代码更难理解和调试的最常见技术之一。

标签: c# linq


【解决方案1】:

问题是 Select 需要返回一个值,而且 Linq 不是为改变集合而设计的。将 select 视为对集合的转换,而不是每个项目的状态更改

也许 foreach 循环是这里最好的解决方案

【讨论】:

  • 嗯,LINQ 也适用于可变集合 - 但并非旨在自行改变它们​​。
【解决方案2】:

我认为你需要的是 ForEach 方法;)

mpwrapper.parser.Discoveries.ToList().ForEach(s => { solution.AddFile("Discoveries", s.DisplayStringName + ".mpx", s); });

【讨论】:

  • 或者坚持使用foreach,这在 IMO 中更清楚。见blogs.msdn.com/b/ericlippert/archive/2009/05/18/…。注意,在不知道Discoveries的类型的情况下,我们不知道这是否会编译...
  • 他说它是一个 IEnumerable 对象,所以它应该编译。我回答了他问的问题,不管它是否更好。但你是对的,使用 foreach 可能会更好。
  • 不,IEnumerable<T> 上没有 ForEach 扩展方法。你当然可以写一篇,但我不建议这样做。
  • 我添加了我忘记的 ToList() 调用;P
  • 与列表顶部的普通 foreach 相比,Linq foreach 会提高性能吗?
【解决方案3】:

如果 Discoveries 是一个列表,那么就这样做

mpwrapper.parser.Discoveries.ForEach(discovery => solution.AddFile("Discoveries", discovery .DisplayStringName + ".mpx", discovery);

如果没有,先转成List :)

【讨论】:

    【解决方案4】:

    List<T>.ForEach 方法可以解决问题。

    但是,IEnumerable<T> 上不存在此方法。

    【讨论】:

      【解决方案5】:

      试试这个:

      mpwrapper.parser.Discoveries.ToList()
          .ForEach(s =>
              solution.AddFile("Discoveries", s.DisplayStringName + ".mpx", s));
      

      【讨论】:

        【解决方案6】:

        LINQ 代表 Language INtegrated Query...但您实际上并没有查询任何东西。

        如果mpwrapper.parser.DiscoveriesList<T>,则可以使用ForEach 方法;或者,如果它是 IEnumerable,您可以随时添加 ForEach 扩展方法……但这更多是一种细微的美学变化,与 LINQ 无关。

        【讨论】:

          【解决方案7】:

          我在 .All 方法中使用了一个小技巧。它只需要一个返回布尔值并且非常整齐地呈现。我在 .All 中包含了一个带有嵌入式 linq 的示例

          configurations.All(c =>
          {
              var gcx = globalConfigurations.FirstOrDefault(gc =>
                  gc.Type == c.Type && configurationGuids.Any(cGuid => gc.Guid == cGuid)
              );
              return true;
          });
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2019-04-04
            • 2018-08-20
            • 2011-07-16
            • 2020-01-31
            • 2015-01-21
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多