【问题标题】:Linq - Is there a IEnumerable.ForEach<T> extension method that I'm missing? [duplicate]Linq - 是否有我缺少的 IEnumerable.ForEach<T> 扩展方法? [复制]
【发布时间】:2011-04-21 20:48:06
【问题描述】:

可能的重复:
Lambda Expression using Foreach Clause…
Why is there not a ForEach extension method on the IEnumerable interface?

这似乎很基本。我正在尝试遍历 IEnumerable 的每个对象。看来我必须先把它放到一个列表中。那正确吗?在我看来,IEnumerable 上应该有一个扩展方法可以做到这一点。我一直不得不纠正自己的问题,我已经厌倦了。我在什么地方想念它吗?

myEnumerable.ToList().ForEach(...)

我想这样做:

myEnumerable.ForEach(...)

【问题讨论】:

标签: .net linq .net-4.0 extension-methods


【解决方案1】:

不,没有。 Eric Lippert 在他的blog 中谈到了为什么这个功能被省略:

很多人问我为什么没有微软提供的“ForEach”序列运算符扩展方法。

总结起来有两个主要原因:

  • 使用 ForEach 违反了所有其他序列运算符所基于的函数式编程原则 - 没有副作用。
  • ForEach 方法不会为语言增加新的表示能力。您可以使用 foreach 语句轻松实现更清晰的相同效果。

【讨论】:

  • 这是个愚蠢的理由。您可以使用 for each 循环来实现 linq 扩展的所有功能。
  • @Micah:当然,你也可以通过直接用 CIL 编写任何 LINQ 扩展方法来实现相同的效果,但我认为它更清晰
  • myEnumerable.ForEach(...) 有什么不清楚的地方?
  • 当你像 myEnumerable.Where(...).Select(...) 这样将一堆调用链接在一起而不只是添加一个 .ForEach(...) 到非常结束它,而不必编写单独的“foreach”代码块。
  • 我希望你们每个人都放轻松,也希望你们所有人不要再标记彼此的 cmets。
【解决方案2】:

不,没有内置的ForEach 扩展方法。不过,自己动手很容易:

public static class EnumerableExtensions
{
    public static void ForEach<T>(this IEnumerable<T> source, Action<T> action)
    {
        if (source == null) throw new ArgumentNullException("source");
        if (action == null) throw new ArgumentNullException("action");

        foreach (T item in source)
        {
            action(item);
        }
    }
}

但是为什么要打扰呢?作为Eric Lippert explains in this blog post,标准的foreach 语句比具有副作用的ForEach 方法更具可读性——在哲学上也更合适:

myEnumerable.ForEach(x => Console.WriteLine(x));
// vs
foreach (var x in myEnumerable) Console.WriteLine(x);

【讨论】:

  • 但是如果我想这样做真的很愚蠢: var results = myenumerable.Where(...).Select(...) foreach(var result in results){ .... }我宁愿做这样的事情:myenumerable.Where(...).Select(...).ForEach(...)
  • @Micah:好吧,如果你想这样做,那就继续在我的回答中使用扩展方法。
  • @Micah:如果你愿意那样做,那就那样做。它是扩展方法中的一行代码。是什么阻止了你?
  • @Eric:我已经完成了,但我仍然不明白为什么不将它作为框架的一部分包含在内的理由。特别是考虑到编写 List 和 .AsParallel() 的人认为值得包括在内。
  • @Micah: List.ForEach 增加价值;因为它可以使用 List 的内部实现细节,所以它可以优化它的实现。 (我不知道它是否真的这样做。)并行的 ForEach 增加了价值;它可以并行执行一系列动作。这些增值都不适用于 IEnumerable 上的扩展方法,它无法查看内部实现细节,也无法并行执行。它既不增加价值也不增加代表性;这只是重写完全合理的循环代码的一种令人困惑且可能更慢的方式。
【解决方案3】:

IEnumerable 没有这个扩展方法。

阅读 Eric Lippert 的博客 here 了解其背后的原因。

所以如果你需要它,你必须自己写它:)

【讨论】:

    【解决方案4】:

    有人谈论它here。它不是内置到框架中的,但您可以滚动自己的扩展方法并以这种方式使用它。据我所知,这可能是你最好的选择。

    我也遇到过这种情况。

    public static class Extensions {
      public static void ForEach<T>(this IEnumerable<T> source, Action<T> action) {
        foreach (var item in source) {
          action(item);
        }
      }
    }
    

    【讨论】:

      【解决方案5】:

      不,没有这样的扩展方法。 List&lt;T&gt; 公开了一个名为 ForEach 的真实方法(自 .NET 2.0 以来一直存在)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-09-23
        • 1970-01-01
        相关资源
        最近更新 更多