2

次のC#ブロックを検討してください。

int resultIndex = 0;

Result firstResult = results.First();
DoAVeryImportOperationWithFirstResult(firstResult);

Console.WriteLine(String.Format("This is the {0} result.", resultIndex++));
yield return firstResult;

foreach(Result result in results)
{
   Console.WriteLine(String.Format("This is the {0} result.", resultIndex++));
   yield return result;
}

Linqとイテレータに精通している場合は、foreachブロックの最初の反復で、結果の最初の結果が2番目の結果ではなく返されることに気付くでしょう。

したがって、基本的にこれが私の問題です。イテレータメソッドから最初の値を取得してから、このメソッドを再起動せずに別の場所で使用することはできません。

誰かがこれの回避策を知っていますか?

4

5 に答える 5

7

foreach他の人は、ループと条件付き実行を使用したアプローチを示しています。これは実際には適切なアプローチforeachですが、何らかの理由でループが不適切な場合に備えて、別のオプションがあります。

using (var iterator = results.GetEnumerator())
{
    if (!iterator.MoveNext())
    {
        // Throw some appropriate exception here.
    }

    Result firstResult = iterator.Current;
    DoAVeryImportOperationWithFirstResult(firstResult);

    Console.WriteLine(String.Format("This is the {0} result.", resultIndex++));
    yield return firstResult;

    while (iterator.MoveNext())
    {
        Result result = iterator.Current;
        Console.WriteLine(String.Format("This is the {0} result.", resultIndex++));
        yield return result;
    }
}
于 2013-02-19T22:07:48.677 に答える
3

明示的に行うだけです:

bool first = true;
foreach(var item in results) {
    if(first) {
        first = false;
        // whatever
    } else {
        // whatever else
    }
}

またはより複雑:

using(var iter = results.GetEnumerator()) {
    if(iter.MoveNext()) {
        // do first things with iter.Current

        while(iter.MoveNext()) {
            // do non-first things with iter.Current
        }
    }
}
于 2013-02-19T22:06:12.130 に答える
3

手動で繰り返す必要があります。

var enumerator = results.GetEnumerator();
enumerator.MoveNext();
yield return enumerator.Current; //first
while(enumerator.MoveNext())
 yield return enumerator.Current; //2nd, ...

すべてのエラーチェックが省略されています...また、廃棄することを忘れないでください。

于 2013-02-19T22:06:13.830 に答える
3
bool isFirst = true;
foreach(Result result in results)
{
   if(isFirst)
   {
      DoAVeryImportOperationWithFirstResult(firstResult);
      isFirst = false;
   }

   Console.WriteLine(String.Format("This is the {0} result.", resultIndex++));
   yield return result;
}
于 2013-02-19T22:07:10.330 に答える
2

スキップを使用する必要があります

foreach(Result result in results.Skip(1))
{
   Console.WriteLine(String.Format("This is the {0} result.", resultIndex++));
   yield return result;
}

または、結果を手動で繰り返します。

イテレータがどのように実装されているかを考えると、実際に期待される動作です。

于 2013-02-19T22:06:17.167 に答える