【问题标题】:is there a .Each() (or .ForEach() ) iterator in the .Net standard library? [duplicate].Net 标准库中是否有 .Each() (或 .ForEach() )迭代器? [复制]
【发布时间】:2011-05-16 17:39:06
【问题描述】:

可能重复:
LINQ equivalent of foreach for IEnumerable<T>

我想知道 .Net 库中是否有类似以下 .Each() 的 IEnumerable 方法

var intArray = new [] {1, 2, 3, 4};
intArrary.Each(Console.WriteLine);

我知道我可以使用foreach 循环或轻松编写这样的扩展方法:

public static class EnumerableExtensions
{
    public static void Each<T>(this IEnumerable<T> enumberable, Action<T> action)
    {
        foreach (var item in enumberable)
        {
            action(item);
        }
    }
}

但是如果库中已经有这样的扩展方法,我希望不要创建自己的方法来弄乱代码。程序员非常需要类似 .Each() (带有一些可以将条件作为额外参数的重载)之类的东西,而且应该已经有了。我说的对吗?

更新

Ruby 开发人员可能会将其识别为 .each() 迭代器。这就是我希望在 C# 中拥有的东西。也许 C# 可以拥有更多像 Ruby 中的迭代器方法。

【问题讨论】:

  • 对于 List 有一个标准的 ForEach 扩展。
  • @James ForEach 不是扩展。它一直都在。
  • @James List.ForEach(Action) 不是扩展方法。它自 .NET 2.0 以来就一直存在
  • @linquize - 好吧,你是对的,我误会它是一种扩展方法。

标签: c# .net


【解决方案1】:

正如其他人所说,IEnumerable&lt;T&gt; 上没有内置任何内容。根据 Eric Lippert 的这篇文章,Linq 团队反对它: http://blogs.msdn.com/b/ericlippert/archive/2009/05/18/foreach-vs-foreach.aspx

Array.ForEach 上有一个静态方法,List&lt;T&gt; 有一个实例方法。 PLINQ 中也有类似 foreach 的语句,但请注意它们并行工作,并且对于极其简单的操作可能导致非常糟糕的性能。 这是 PLINQ 中的一种方法:http://msdn.microsoft.com/en-us/library/dd383744.aspx

这里是关于 PLINQ 的一般指南:http://msdn.microsoft.com/en-us/library/dd460688.aspx

如果您在 ParrallelEnumerable 部分中四处寻找,我无法找到确切的文章,但它提供了有关如何提高在代码中使用并行性的性能的警告和提示

如果需要,我建议创建 2 个版本,一个包含索引器,一个不包含。这可能非常有用,并且可以保存一个选择语句来获取索引。 例如

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

public static void ForEach<T>(IEnumerable<T> enumerable,Action<T,int> action)
{
    int index = 0;
    foreach(var item in enumerable) action(item,index++);
}

我还会包括参数验证,因为这些是公共方法。

【讨论】:

  • 您能否详细说明一下“性能”和“索引器”?
  • 不应该是action(item)吗?否则你要对整个可枚举执行action
  • 是的,没错。我很久以前就写了这些……我会相应地更新它们。
  • 第一个参数缺少this
【解决方案2】:

是的。

someList.ForEach(x => Console.WriteLine(x));

或者使用数组:

Array.ForEach(someArray, x => Console.WriteLine(x));

请注意,在最后一个示例中,您必须调用 Array 类的静态方法

编辑:命名空间是:System.Collections.Generic 用于 List 方法,System 用于 Array 方法

【讨论】:

  • 我应该使用哪个命名空间?
  • -1 ForEach 是List&lt;T&gt; 上的实例方法 - 数组没有此实例方法。
  • Andrew Hare - 请在投反对票之前尝试编译代码。 ForEach 也可用作 Array 类的静态方法:msdn.microsoft.com/en-us/library/zecdkyw2.aspx
  • @Raphael - 我删除了我的反对票,因为您编辑了答案以包含 Array.ForEach。虽然它不是 OP 要求的实例或扩展方法,但它确实完成了工作。
  • Andrew Hare - 没有伤害:P。我应该在我的第一个答案中包含 Array.ForEach,但 List 的 ForEach 是我能想到的第一个
【解决方案3】:

System.Collections.List 上有一个 ForEach 方法,但 IEnumerable 上没有。请注意,这也不是 LINQ 的一部分(它已经存在于 .NET 2.0 中)。

乍一看,您会认为这是 LINQ 的一部分,因为它是对普通 List 功能的一种扩展。然而,LINQ 更多的是关于分组、过滤和转换数据。如果你仔细观察,大多数(如果不是全部,我不是 Jon Skeet,我不知道那些东西!)LINQ 方法返回某种 IEnumerable。

不过,您可能想看看MoreLinq。这是一个开源项目,它为现有的 LINQ to Objects 添加了一些关键功能,其中之一是您想要的 ForEach 方法(在这种情况下适用于任何 IEnumerable,因此它也适用于您的数组)。

【讨论】:

  • Rx 在 EnumerableEx 中包含 ForEach for IEnumerable ...它肯定会成为 BCL 的一部分,在未来的版本中将许多其他运算符添加到 IEnumerable 作为扩展方法。
  • 我只是仔细检查了一下,它不是最新版本的一部分……哎呀。 :S 我猜他们删除了它。但是,Run 和 Do 会做同样的事情,Run 返回 void 和 Do 返回输入 IEnumerable 不变。
【解决方案4】:

不,很遗憾,没有。 (我想这个问题之前已经讨论过,但我目前找不到。)

由于一些奇怪的历史事故,ForEach 方法最终在List&lt;T&gt; 上,而不是在IEnumerable&lt;T&gt; 上,它更有意义,并且由于向后兼容,这永远无法修复。

自从扩展方法存在以来,添加一个ForEach(this IEnumerable&lt;T&gt;, ...)扩展方法被一遍又一遍地请求,但它通常被拒绝,因为它会导致混乱的行为:因为实例方法总是在扩展方法之前选择,这意味着所有IEnumerables 得到相同的处理,除了Lists,他们不允许在 BCL 中出现这种不一致。

因此,地球上几乎每个 .NET 项目现在都以您上面描述的代码开始:

namespace IEnumerableExtensions
{
    public static class IEnumerableExtensions
    {
        public static void ForEach<T>(this IEnumerable<T> xs, Action<T> f)
        {
            foreach (var x in xs) f(x);
        }
    }
}

【讨论】:

  • 嗯.. 很奇怪。为什么不为该方法命名,例如 .Each()?这就是红宝石所具有的。
  • @Bryan Shen:你得问问 BCL 团队 :-) 不过我有几个想法:与foreach 保持一致,与Parallel.ForEach 保持一致以及与List&lt;T&gt;.ForEach 重复.
  • 这是完全错误的。 LINQ 团队希望将其保留在不可变功能上,而 foreach 完全是关于副作用的。没有人会关心列表中的 ForEach 是否使用索引器而不是 GetNext/MoveNext。
  • @Jörg W Mittag:很好。根据您的解释,我决定将其合并到我自己的库中。
【解决方案5】:

只有 List&lt;T&gt; 提供 ForEach 方法 - 对于所有其他类型,您将必须滚动自己的扩展方法。

【讨论】:

  • 我不敢相信这不是 IEnumberable 的扩展方法
  • 数组有一个,正如 Raphael 指出的那样。
  • @TheCodeMonk - Array 类有一个只对数组进行操作的静态方法。这与在 IEnumerable&lt;T&gt; 上运行的 扩展方法 非常不同,这似乎是 OP 真正想要的。
【解决方案6】:

取决于框架版本

.net 3.5 和 4.0 有一个ForEach 方法

【讨论】:

  • -1 在任何版本的框架中,数组上都没有ForEach 方法。
  • @Andrew Hare:ForEach 可用作 Array 类的静态方法。请不要在你的脑海中编译。使用机器
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-09-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-17
相关资源
最近更新 更多