【问题标题】:Linq style "For Each" [duplicate]Linq 风格“For Each”[重复]
【发布时间】:2010-12-03 07:49:22
【问题描述】:

“For each”操作是否有任何 Linq 样式语法?

例如,将基于一个集合的值添加到另一个已经存在的集合:

IEnumerable<int> someValues = new List<int>() { 1, 2, 3 };

IList<int> list = new List<int>();

someValues.ForEach(x => list.Add(x + 1));

代替

foreach(int value in someValues)
{
  list.Add(value + 1);
}

【问题讨论】:

标签: c# .net linq foreach


【解决方案1】:

使用 ToList() 扩展方法是您的最佳选择:

someValues.ToList().ForEach(x => list.Add(x + 1));

BCL 中没有直接实现 ForEach 的扩展方法。


虽然在 BCL 中没有执行此操作的扩展方法,但在 System 命名空间中仍有一个选项...如果您将 Reactive Extensions 添加到你的项目:

using System.Reactive.Linq;

someValues.ToObservable().Subscribe(x => list.Add(x + 1));

这与上面使用 ToList 的最终结果相同,但(理论上)更有效,因为它将值直接流式传输到委托。

【讨论】:

  • 请记住,这对于很长的列表并不理想,因为它会在循环之前复制整个列表。
  • 调用ToList 后跟ForEach 涉及对原始集合进行两次迭代。我更喜欢标准的 foreach 循环任何一天:更少的打字,更易读和更好的性能:foreach (var x in someValues) list.Add(x + 1);
  • 对于任何看到这个并认为这是一个很好的答案的人,它不是。这是疯狂的低效。请参阅诺多林的回答,了解正确的做事方式。
  • 公平点,但我想补充一点:理论上它可能效率低下,但我使用的大多数内存列表往往少于十几个项目。性能。问题通常在其他地方,所以我认为断然声明这个答案很糟糕是一个过早的优化。问题是这个 syntax 是否可用,这与你在普通的 .NET 3.5 SP1 上得到的一样接近,而无需自己编写扩展方法。我希望在 BCL 中有一个 ForEach 扩展方法,但它在当前框架中不可用。
  • @Luke:没有特别的好处,但这也不是问题所在。无论如何,我认为这是一场茶杯中的风暴:在大多数情况下,我敢打赌你根本感觉不到性能差异。
【解决方案2】:

没有任何内置功能,但您可以轻松创建自己的扩展方法来做到这一点:

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

【讨论】:

  • 为什么没有内置任何东西?我错过了什么吗?这似乎是非常需要的基本功能。
  • @DanCsharpster 因为 linq 方法不应该有副作用
【解决方案3】:

没有 Linq ForEach 扩展。但是,如果您愿意直接使用 ListList 类上有一个 ForEach 方法。

不管怎样,标准的foreach 语法会给你想要的结果,而且它可能更容易阅读:

foreach (var x in someValues)
{
    list.Add(x + 1);
}

如果你坚持要一个 Linq 风格的扩展。自己实现这个很简单。

public static void ForEach<T>(this IEnumerable<T> @this, Action<T> action)
{
   foreach (var x in @this)
      action(x);
}

【讨论】:

    【解决方案4】:

    官方的 MS 行是“因为它不是函数式操作”(即它是有状态的操作)。

    你不能这样做吗:

    list.Select( x => x+1 )
    

    或者如果你真的需要它在一个列表中:

    var someValues = new List<int>( list.Select( x => x+1 ) );
    

    【讨论】:

    • 您对功能操作与有状态操作有一定的看法。但是,F# 被设计为函数长度,并且具有等效的ForEach 方法。
    • 你能给“官方MS线”一个参考吗?我有兴趣阅读他们的其余部分。
    • 我可能不应该使用“官方”这个词,但这是我想到的博客:blogs.msdn.microsoft.com/ericlippert/2009/05/18/…
    【解决方案5】:

    ArrayList&lt;T&gt; 类已经有 ForEach 方法,尽管只有这个特定的实现。 (注意前者是static,顺便说一下)。

    不确定它是否真的比foreach 语句提供了很大的优势,但您可以编写一个扩展方法来为所有IEnumerable&lt;T&gt; 对象完成这项工作。

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

    这将允许您在问题中发布的确切代码按您的意愿工作。

    【讨论】:

    • 谢谢,很明显我可以自己编写扩展。我只是想在这样做之前尽可能使用内置的东西。
    • 是的,这很公平。我还确保我不会重新发明 BCL 功能。然而,在这种情况下,没有。
    • Array 类没有 ForEach 方法 :) 但 Microsoft.Practices.ObjectBuilder2 命名空间中有一个“EnumerableExtensions”statşc 类。它有 IEnumerable 的 foreach 方法 :)
    【解决方案6】:

    在标准 Linq 中没有类似的东西,但在 MoreLinq 中有一个 ForEach 运算符。

    【讨论】:

      猜你喜欢
      • 2013-09-28
      • 2015-10-02
      • 1970-01-01
      • 2010-12-21
      • 1970-01-01
      • 1970-01-01
      • 2015-09-19
      • 2023-03-18
      • 2016-05-06
      相关资源
      最近更新 更多