2011-01-31 10 views
2

ソース関数(IEnumerableを返す)の結果を他の処理関数(それぞれが受け取り、IEnumerableを返す)のリストを通して渡す必要があります。奇妙な委任参照の振る舞い

これまではすべて問題ありませんでしたが、処理関数が入力エコーメントに対して複数のループを実行できるようにする必要があります。

IEnumerable<T>を渡すのではなく、入力パラメータをFunc<IEnumerable<T>>に変更し、必要に応じて各関数が列挙型を再起動できるようにすることを考えました。

残念ながら、私は今、最終処理機能が要求をチェーンに戻すのではなく、自分自身を呼び出しているスタックオーバーフローを取得しています。

サンプルコードは少し工夫されていますが、うまくいけば私が達成しようとしていることのアイデアが得られます。

class Program 
{ 
    public static void Main(string[] args) 
    { 
     Func<IEnumerable<String>> getResults =() => GetInputValues("A", 5); 

     List<String> valuesToAppend = new List<String>(); 

     valuesToAppend.Add("B"); 
     valuesToAppend.Add("C"); 

     foreach (var item in valuesToAppend) 
     { 
      getResults =() => ProcessValues(() => getResults(),item); 
     } 

     foreach (var item in getResults()) 
     { 
      Console.WriteLine(item); 
     } 

    } 

    public static IEnumerable<String> GetInputValues(String value, Int32 numValues) 
    { 
     for (int i = 0; i < numValues; i++) 
     { 
      yield return value; 
     } 
    } 

    public static IEnumerable<String> ProcessValues(Func<IEnumerable<String>> getInputValues, String appendValue) 
    { 
     foreach (var item in getInputValues()) 
     { 
      yield return item + " " + appendValue; 
     } 
    } 

} 

答えて

4

getResultsない値変数として捕捉されます。私は(それは複雑なようだ)本当にあなたがここで使用している全体的なアプローチ好きではないが、あなたは、キャプチャを変更することにより、StackOverflowのを修正することができるはずです:サイドノートで

foreach (var item in valuesToAppend) 
    { 
     var tmp1 = getResults; 
     var tmp2 = item; 
     getResults =() => ProcessValues(() => tmp1(),tmp2); 
    } 

IEnumerable[<T>]はすでにあるちょっと再現性、あなたは、単に別の時間foreachを呼ぶ - であることはIEnumerator[<T>]であることではありません(Reset()にもかかわらず) - だけでなく、私は以来、これまでに列挙を繰り返す必要がせず、それはこのをやろうとしてやって価値があると思います一般的なケースは、単に動作することを保証することはできません。


ここでは同じ結果と単純に(IMO)の実装です:

using System; 
using System.Collections.Generic; 
using System.Linq; 
class Program { 
    public static void Main() { 
     IEnumerable<String> getResults = Enumerable.Repeat("A", 5); 
     List<String> valuesToAppend = new List<String> { "B", "C" }; 
     foreach (var item in valuesToAppend) { 
      string tmp = item; 
      getResults = getResults.Select(s => s + " " + tmp); 
     } 
     foreach (var item in getResults) { 
      Console.WriteLine(item); 
     } 
    } 
} 
+0

最初の例では、StackOverflowのを避けたが、今返す:ACC、ACCなど – rob

+0

@rob - (完了申し訳ありませんが、修正されます) –

+0

ありがとうございます。今働いて!実世界の処理コードはメモリ内の多数の項目を処理する必要があるため、メモリが少ない状況でも動作させるには複数のパスが必要です。私は、IEnumerableがそれ自身で繰り返しできるほど巧妙であることを認識していませんでした。私はその動作に頼るべきではありません。 – rob