Existing LINQ extension method similar to Parallel.For? [duplicate]

自作多情 提交于 2019-11-29 02:32:55

问题


Possible Duplicate:
LINQ equivalent of foreach for IEnumerable<T>

The linq extension methods for ienumerable are very handy ... but not that useful if all you want to do is apply some computation to each item in the enumeration without returning anything. So I was wondering if perhaps I was just missing the right method, or if it truly doesn't exist as I'd rather use a built-in version if it's available ... but I haven't found one :-)

I could have sworn there was a .ForEach method somewhere, but I have yet to find it. In the meantime, I did write my own version in case it's useful for anyone else:

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

usage is:

myEnumerable.For<MyClass>(delegate(MyClass item) { item.Count++; });


回答1:


Shedding a little more light on why:

LINQ is functional in nature. It is used to query data and return results. A LINQ query shouldn't be altering the state of the application (with some exceptions like caching). Because foreach doesn't return any results, it doesn't have many uses that don't involve altering the state of something besides what you are passing in to it. And if you need a Foreach() extension method, it is easy to roll your own.

If, on the other hand, what you want is to take input and call a function on each item that returns a result, LINQ provides a way through its select method.

For example, the following code calls a function delegate on every item in a list, returning true if that item is positive:

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



回答2:


Actually, the Reactive Extensions framework from Microsoft Research did add this functionality. In the System.Interactive assembly they've included a Run() and a Do() extensions to IEnumerable<T>.

Do(action) will execute the action on each element and yield it back. This is useful for adding logging to a linq query for example:

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

This will result in:

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

Run(action) is like a foreach loop, which means its folding the sequence which executing the action.

You can read more about it here: http://community.bartdesmet.net/blogs/bart/archive/2009/12/26/more-linq-with-system-interactive-the-ultimate-imperative.aspx

The Rx framework can be found here: http://msdn.microsoft.com/en-us/devlabs/ee794896.aspx




回答3:


The ForEach method on List<T> does this. You could wrap your collection in a list and then use that call, but that's not really a nice thing to do. Looks like you'll have to roll your own.




回答4:


Already discussed here and there.

Im too drowsy to remember but, basically, a .ForEach method in a single thread application is functionally equivalent the already existing foreach statement. From what I understand, the main difference is that a ForEach could be parallized but that would introduce unwanted behaviours too easily.



来源:https://stackoverflow.com/questions/317874/existing-linq-extension-method-similar-to-parallel-for

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!