문제

I have a code like:

        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

In the code above all is working fine but when I use next:

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

It prints (in brackets second loop): 0 1 (3 4) 2 instead of 0 1 (0 1 2 3 4) 2 3 4 I tested It on List and Collection and they do It right. How can I to achive what I need?

도움이 되었습니까?

해결책

You can't because you have made your code surface a single enumerator, itself a mistake IMO. A better version would be, for me:

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

The compiler will create the right devices to achieve this with separate enumerators.

Unless you are writing for .NET 1.1, then if you find yourself manually writing an enumarator, there's a very good chance that you are doing it the hard way, and getting it wrong as a bonus.

If you really must do it the hard way:

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; }
    } 
}

The significance here is that different instances of TEnumerator allow the same T instance to be iterated separately.

다른 팁

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

First always use braces, while you indenting matches what will happen another if in there will confuse things.

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

But you problem: you only have one counter per instance of T, and you are using the same instance. Therefore you do through once. If you want to allow concurrent enumerations the enumerator object will need to be separate with GetEnumerator returning a new instance each time.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top