4

私は次のようなコードを持っています:

        class T : IEnumerable, IEnumerator
        {
            private int position = -1;

            public T() { }

            public IEnumerator GetEnumerator() { return this; }

            public object Current { get { return position; } }

            public bool MoveNext()
            {
                position++;
                return (position < 5);
            }

            public void Reset() { position = -1; }
        }

//Using in code:
T t = new T();
foreach (int i in t)
 //to do something

上記のコードではすべてが正常に機能していますが、次に使用する場合:

foreach (int i in t)
   if (i == 2)
     foreach (int p in t)
       //print p
   else
       //print i

それは(括弧内の2番目のループで)出力します:0 1(0 1 2 3 4)の代わりに0 1(3 4)2 3 4私はリストとコレクションでそれをテストしました、そして彼らはそれを正しく行います。どうすれば必要なものを達成できますか?

4

2 に答える 2

9

コード表面を単一の列挙子にしたので、それ自体が間違いのIMOであるためにできません。私にとって、より良いバージョンは次のようになります。

class T : IEnumerable<int> {
    public IEnumerator<int> GetEnumerator() {
        int i = 0;
        while(i < 5) {
            yield return i;
            i++;
        }
    }
    IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }
}

コンパイラーは、個別の列挙子を使用してこれを実現するための適切なデバイスを作成します。

.NET 1.1用に書いているのでない限り、手動で列挙子を書いていることに気付いた場合は、それを困難な方法で行っており、ボーナスとして間違っている可能性が非常に高くなります。

あなたが本当にそれを難し​​い方法でやらなければならないなら:

class T : IEnumerable<int>
{
    public T() { }

    public IEnumerator<int> GetEnumerator() { return new TEnumerator(); }
    IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }
    private class TEnumerator : IEnumerator<int>
    {
        private int position = -1;
        public int Current { get { return position; } }
        object IEnumerator.Current { get { return Current; } }
        void IDisposable.Dispose() {}
        public bool MoveNext()
        {
            position++;
            return (position < 5);
        }
        public void Reset() { position = -1; }
    } 
}

ここでの重要性は、の異なるインスタンスが同じインスタンスを別々に繰り返すことをTEnumerator可能にすることです。 T

于 2011-10-05T08:18:50.830 に答える
5
foreach (int i in t)
   if (i == 2)
     foreach (int p in t)
       //print p
   else
       //print i

最初は常に中かっこを使用しますが、一致をインデントすると、そこで別のことが起こるifと混乱します。

foreach (int i in t) {
   if (i == 2) {
     foreach (int p in t) {
       //print p
      }
   } else {
       //print i
   }
 }

ただし、問題があります。インスタンスごとに1つのカウンターしかなくT、同じインスタンスを使用しています。したがって、あなたは一度やり遂げます。GetEnumerator同時列挙を許可する場合は、列挙子オブジェクトを分離して、毎回新しいインスタンスを返す必要があります。

于 2011-10-05T08:21:00.330 に答える