Существующий метод расширения LINQ, похожий на Parallel.For?[дубликат]

StackOverflow https://stackoverflow.com/questions/317874

Вопрос

Возможный Дубликат:
LINQ эквивалент foreach для IEnumerable<T>

Методы расширения 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++; });

Это было полезно?

Решение

Проливая немного больше света на то, почему:

LINQ является функциональным по своей природе.Он используется для запроса данных и возврата результатов.Запрос LINQ не должен изменять состояние приложения (за некоторыми исключениями, такими как кэширование).Поскольку foreach не возвращает никаких результатов, у него не так много применений, которые не предполагают изменения состояния чего-либо, кроме того, что вы ему передаете.И если вам нужен метод расширения Foreach(), он является легко свернуть самостоятельно.

Если, с другой стороны, то, что вы хотите, это принять входные данные и вызвать функцию для каждого элемента, которая возвращает результат, LINQ предоставляет способ с помощью своего метода select .

Например, следующий код вызывает функцию делегирования для каждого элемента в списке, возвращая значение 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 Framework от Microsoft Research действительно добавила эту функциональность.В System.Interactive сборка, в которую они включили Run() и a Do() расширения к IEnumerable<T>.

Делать (действие) выполнит действие над каждым элементом и вернет его обратно.Это полезно, например, для добавления ведения журнала в запрос 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 можно было бы распараллелить, но это слишком легко привело бы к нежелательному поведению.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top