Linq风格"For Each"

Ste*_*ger 182 .net c# linq foreach

可能重复:
Linq相当于IEnumerable的foreach

是否有"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));
Run Code Online (Sandbox Code Playgroud)

代替

foreach(int value in someValues)
{
  list.Add(value + 1);
}
Run Code Online (Sandbox Code Playgroud)

Mar*_*ann 264

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

someValues.ToList().ForEach(x => list.Add(x + 1));
Run Code Online (Sandbox Code Playgroud)

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


虽然有一个在没有扩展方法BCL做这个,也就是还处于一个选项System命名空间......如果你添加无扩展到您的项目:

using System.Reactive.Linq;

someValues.ToObservable().Subscribe(x => list.Add(x + 1));
Run Code Online (Sandbox Code Playgroud)

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

  • 对于任何看到这个并认为它是一个好答案的人,它不是.这是疯狂的低效率.请参阅Noldorin关于正确做事方式的答案. (34认同)
  • 调用`ToList`后跟`ForEach`涉及遍历原始集合两次.我更喜欢任何一天的标准`foreach`循环:更少的输入,更可读和更好的性能:`foreach(var x in someValues)list.Add(x + 1);` (8认同)
  • 公平点,但我想补充一点:理论上它可能效率低下,但我使用的大多数内存列表往往只有不到十几项.逆足 问题通常出现在其他地方,所以我认为断然说这个答案很糟糕是不成熟的优化.问题是这个*语法*是否可用,并且这与普通的.NET 3.5 SP1上的接近,而不是自己编写扩展方法.我希望在BCL中有一个ForEach扩展方法,但它在当前框架中不可用. (6认同)
  • 请记住,这对于很长的列表来说并不理想,因为它在循环之前会复制整个列表. (4认同)
  • @Luke:没有特别的好处,但这也不是问题。无论如何,我认为这是茶杯里的风暴:在大多数情况下,我敢打赌你根本感觉不到性能差异。 (2认同)
  • @MarkSeemann在测试`someValues.ToObservable()的新答案.订阅(...)`似乎比`ToList()慢50倍.ForEach(...)`和`Select(... ).ToList()` (2认同)
  • @qujck 但*理论上*,它更有效率!;) (2认同)

Nol*_*rin 95

ArrayList<T>班已经有ForEach方法,但只有该种具体实施.(注意前者是static顺便说一下).

不确定它是否真的比foreach声明提供了很大的优势,但你可以编写一个扩展方法来为所有IEnumerable<T>对象完成工作.

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

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

  • 谢谢,很明显我可以自己编写扩展。我只想在执行此操作之前尽可能使用内置的东西。 (2认同)
  • 是的,这很公平.我也确保我不会重新发明BCL功能.在这种情况下,没有. (2认同)
  • Array类没有ForEach方法:)但Microsoft.Practices.ObjectBuilder2命名空间中有一个"EnumerableExtensions"statşc类.它有IEnumerable的foreach方法:) (2认同)

Luk*_*keH 31

内置没有任何内容,但您可以轻松创建自己的扩展方法来执行此操作:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

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

stu*_*ith 18

官方MS系列是"因为它不是功能操作"(即它是一个有状态的操作).

你做不到这样的事情:

list.Select( x => x+1 )
Run Code Online (Sandbox Code Playgroud)

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

var someValues = new List<int>( list.Select( x => x+1 ) );
Run Code Online (Sandbox Code Playgroud)

  • 您有关于功能与有状态操作的观点.但是,F#被设计为一个函数长度,并且具有等效的"ForEach"方法. (5认同)

dus*_*ell 6

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

无论如何,标准foreach语法将为您提供您想要的结果,并且可能更容易阅读:

foreach (var x in someValues)
{
    list.Add(x + 1);
}
Run Code Online (Sandbox Code Playgroud)

如果您坚决想要 Linq 风格的扩展。自己实现这个很简单。

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