14

可能重复:
LINQ 等效于 IEnumerable<T> 的 foreach

用于 ienumerable 的 linq 扩展方法非常方便......但如果您只想对枚举中的每个项目应用一些计算而不返回任何内容,那么它就没有那么有用了。所以我想知道我是否只是错过了正确的方法,或者它是否真的不存在,因为如果它可用的话我宁愿使用内置版本......但我还没有找到一个:-)

我可以发誓在某个地方有一个 .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

4 回答 4

17

进一步说明原因:

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();        
    }
于 2008-11-25T18:59:50.720 回答
10

实际上,Microsoft Research 的 Reactive Extensions 框架确实添加了这个功能。在System.Interactive程序集中,他们包含了 aRun()和 a 的Do()扩展IEnumerable<T>

Do(action)将对每个元素执行操作并将其返回。这对于将日志记录添加到 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

Run(action)就像一个 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

于 2010-05-07T10:26:21.143 回答
3

ForEach 方法就是List<T>这样做的。您可以将您的集合包装在一个列表中,然后使用该调用,但这并不是一件好事。看来你得自己动手了。

于 2008-11-25T16:15:14.780 回答
-1

已经在这里那里讨论过了。

我太困了,记不住,但基本上,单线程应用程序中的 .ForEach 方法在功能上等同于已经存在的 foreach 语句。据我了解,主要区别在于 ForEach 可以并行化,但这会很容易引入不需要的行为。

于 2008-11-25T16:46:50.007 回答