2

を使用しIEnumerableて一連の値、具体的には Excel のような列ヘッダーのリストを生成したいと考えています。

private IEnumerable<string> EnumerateSymbolNames()
{
  foreach (var sym in _symbols)
  {
    yield return sym;
  }

  foreach (var sym1 in _symbols)
  {
    foreach (var sym2 in _symbols)
    {
      yield return sym1 + sym2;
    }
  }

  yield break;
}
private readonly string[] _symbols = new string[] { "A", "B", "C", ...};

foreachループから値を取得すると、これはうまく機能します。しかし、私が望むのは、反復子ブロックをステート マシンとして使用し、ユーザー アクションに応答して次に使用可能な列ヘッダーを取得することです。そして、これは、生成された値を消費することであり、私が問題に遭遇した場所です。

これまで私は試しました

return EnumerateSymbolNames().Take(1).FirstOrDefault();

return EnumerateSymbolNames().Take(1).SingleOrDefault();

return EnumerateSymbolNames().FirstOrDefault();

var enumerator = EnumerateSymbolNames().GetEnumerator();
enumerator.MoveNext();
return enumerator.Current;

...しかし、これらのどれも機能していません。(すべて繰り返し「A」を返します。)この質問への回答に基づいて、私が望むことは可能でさえあると思います-その投稿への回答のいくつかは私の最後のものと同様のテクニックを示唆しています.

いいえ、これは宿題ではありません:)

4

3 に答える 3

4

を使用する場合GetEnumerator、反復ごとに同じ列挙子を使用する必要があります。GetEnumerator をもう一度呼び出すと、コレクションの最初からやり直されます。

を使用する場合Takeは、最初Skipに処理済みのレコード数を取得する必要があります。

于 2012-09-18T12:49:47.740 に答える
0

このコードは私のために働いた...

var states = EnumerateSymbolNames();
var stateMachine = states.GetEnumerator();

do
{
  //something
} while (stateMachine.MoveNext());

そのループ内で結果を出力すると、次の出力が正常に生成されました。

A
B
C
...
AA
AB
AC
...
BA
BB
...

これはあなたが意図したものだと思います...

于 2012-09-18T13:18:55.080 に答える
0

@cadrell0 の回答と @Mr Steak のコメントの両方が指摘しているように、私がする必要があったのは、によって返された列挙子への参照を保持することでしたEnumerateSymbolNames().GetEnumerator()

ループ内にいる場合foreach、これは暗黙的に行われます。イテレータ変数は列挙子をラップします。これは (私が推測しているように) スコープがループにローカルに設定されます。だから -- そしてこれが重要な部分です -- イテレータブロックがそうするとき (と同等)

enumerator.MoveNext();
return enumerator.Current;

...常に同じ列挙子を使用しています。私が行っていたのは、毎回異なる(新しい)列挙子を作成/取得することでした。そして予想通り、それは常にシーケンスの最初の位置から始まりました。これは、おそらく私以外の誰にとっても明らかでした。後から考えると、私にも明らかなようです。(毎回同じ列挙子を取得すると仮定して、列挙子をシーケンスのシングルトン プロパティの一種と考えていました。)

以下は私が望むことを行います:

public class SymbolGenerator
{
    private readonly string[] _symbols = { "A", "B", "C", ... };

    private readonly IEnumerator<string> _enumerator;

    public SymbolGenerator()
    {
        _enumerator = EnumerateSymbols().GetEnumerator();
    }

    public string GetNextSymbol()
    {
        _enumerator.MoveNext();
        return _enumerator.Current;
    }

    private IEnumerable<string> EnumerateSymbols()
    {
        // (unchanged)
    }
}
于 2012-09-29T16:14:14.037 に答える