Существующий метод расширения LINQ похож на Parallel.For?
Возможный дубликат:
LINQ эквивалент foreach для IEnumerable;
Методы расширения linq для ienumerable очень удобны... но не очень полезны, если все, что вы хотите сделать, это применить некоторые вычисления к каждому элементу в перечислении, ничего не возвращая. Поэтому мне было интересно, если, возможно, я просто пропустил правильный метод, или он действительно не существует, так как я бы предпочел использовать встроенную версию, если она доступна... но я не нашел ее:-)
Я мог бы поклясться, что где-то был метод.ForEach, но я еще не нашел его. Тем временем я написал свою собственную версию на случай, если она пригодится кому-то еще:
using System.Collections;
using System.Collections.Generic;
public delegate void Function<T>(T item);
public delegate void Function(object item);
public static class EnumerableExtensions
{
public static void For(this IEnumerable enumerable, Function func)
{
foreach (object item in enumerable)
{
func(item);
}
}
public static void For<T>(this IEnumerable<T> enumerable, Function<T> func)
{
foreach (T item in enumerable)
{
func(item);
}
}
}
использование это:
myEnumerable.For<MyClass>(delegate(MyClass item) { item.Count++; });
4 ответа
Пролить немного больше света на почему:
LINQ носит функциональный характер. Он используется для запроса данных и возврата результатов. Запрос LINQ не должен изменять состояние приложения (за некоторыми исключениями, такими как кеширование). Поскольку foreach не возвращает никаких результатов, он не имеет много применений, которые не включают изменение состояния чего-либо, кроме того, что вы ему передаете. И если вам нужен метод расширения Foreach(), вы можете легко создать свой собственный.
Если, с другой стороны, вы хотите получить входные данные и вызвать функцию для каждого элемента, который возвращает результат, LINQ предоставляет способ выбора метода.
Например, следующий код вызывает делегирование функции для каждого элемента в списке, возвращая значение true, если этот элемент является положительным:
static void Main(string[] args)
{
IEnumerable<int> list = new List<int>() { -5, 3, -2, 1, 2, -7 };
IEnumerable<bool> isPositiveList = list.Select<int, bool>(i => i > 0);
foreach (bool isPositive in isPositiveList)
{
Console.WriteLine(isPositive);
}
Console.ReadKey();
}
На самом деле, инфраструктура Reactive Extensions от Microsoft Research действительно добавила эту функцию. в System.Interactive
собрание они включили Run()
и Do()
расширения до IEnumerable<T>
,
Do (действие) выполнит действие для каждого элемента и вернет его. Это полезно для добавления регистрации в запрос linq, например:
var res = GetRandomNumbers(100).Take(10)
.Do(x => Console.WriteLine("Source -> {0}", x))
.Where(x => x % 2 == 0)
.Do(x => Console.WriteLine("Where -> {0}", x))
.OrderBy(x => x)
.Do(x => Console.WriteLine("OrderBy -> {0}", x))
.Select(x => x + 1)
.Do(x => Console.WriteLine("Select -> {0}", x));
Это приведет к:
Source -> 96
Where -> 96
Source -> 25
Source -> 8
Where -> 8
Source -> 79
Source -> 25
Source -> 3
Source -> 36
Where -> 36
Source -> 51
Source -> 53
Source -> 81
OrderBy -> 8
Select -> 9
9
OrderBy -> 36
Select -> 37
37
OrderBy -> 96
Select -> 97
97
Выполнение (действие) похоже на цикл foreach, что означает сворачивание последовательности, выполняющей действие.
Вы можете прочитать больше об этом здесь: http://community.bartdesmet.net/blogs/bart/archive/2009/12/26/more-linq-with-system-interactive-the-ultimate-imperative.aspx
Платформу Rx можно найти здесь: http://msdn.microsoft.com/en-us/devlabs/ee794896.aspx
Метод ForEach на List<T>
Является ли это. Вы можете поместить свою коллекцию в список и затем использовать этот вызов, но это не очень хорошая вещь. Похоже, вам придется кататься самостоятельно.
Я слишком сонный, чтобы помнить, но, по сути, метод.ForEach в однопоточном приложении функционально эквивалентен уже существующему выражению foreach. Из того, что я понимаю, главное отличие состоит в том, что ForEach может быть парализован, но это слишком легко вводит нежелательное поведение.