14

重複の可能性:
IEnumerable<T> の foreach に相当する LINQ

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アセンブリには、 および への拡張機能が含まれてRun()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 に答える