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

当前回答

Array和List<T>类已经有ForEach方法,尽管只有这个特定的实现。(顺便说一下,注意前者是静态的)。

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

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

这将允许您在问题中发布的确切代码按照您想要的方式工作。

其他回答

微软官方的说法是“因为它不是一个功能性操作”(即它是一个有状态操作)。

你就不能这样做吗:

list.Select( x => x+1 )

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

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

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

不管怎样,标准的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);
}

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

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

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


虽然BCL中没有这样做的扩展方法,但在System命名空间中仍然有一个选项…如果你在项目中添加响应式扩展:

using System.Reactive.Linq;

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

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

它没有任何内置的东西,但你可以很容易地创建自己的扩展方法来做它:

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

在标准Linq中没有这样的东西,但是在MoreLinq中有一个ForEach操作符。