Стиль Linq "Для каждого"

Возможный дубликат:
Linq эквивалент foreach для IEnumerable

Есть ли какой-либо синтаксис стиля 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);
}

Ответ 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, но является (теоретически) более эффективным, поскольку оно передает значения непосредственно делегату.

Ответ 2

Array и List<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);
}

Это позволит точно указать код, который вы разместили в своем вопросе, для работы так, как вы хотите.

Ответ 3

Нет ничего встроенного, но вы можете легко создать свой собственный метод расширения для этого:

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

Ответ 4

Официальная строка MS "потому что это не функциональная операция" (т.е. это операция с состоянием).

Не могли бы вы сделать что-то вроде:

list.Select( x => x+1 )

или если вам это действительно нужно в списке:

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

Ответ 5

В стандартном Linq нет ничего подобного, но есть оператор ForEach в MoreLinq.

Ответ 6

Нет расширения 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);
}