C# 如何为多个foreach实现正确的IEnumerator接口?

C# 如何为多个foreach实现正确的IEnumerator接口?,c#,.net,ienumerable,ienumerator,C#,.net,Ienumerable,Ienumerator,我的代码如下: class T : IEnumerable, IEnumerator { private int position = -1; public T() { } public IEnumerator GetEnumerator() { return this; } public object Current { get { return positio

我的代码如下:

        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
它打印(在第二个循环的括号中):01(34)2而不是01(01 2 3 4)2 3 4 我在列表和集合中测试了它,他们做得很好。
我怎样才能得到我需要的呢?

你不能,因为你把你的代码表面变成了一个单一的枚举器,在我看来这本身就是一个错误。对我来说,更好的版本是:

class T : IEnumerable<int> {
    public IEnumerator<int> GetEnumerator() {
        int i = 0;
        while(i < 5) {
            yield return i;
            i++;
        }
    }
    IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }
}
T类:IEnumerable{
公共IEnumerator GetEnumerator(){
int i=0;
而(i<5){
收益率i;
i++;
}
}
IEnumerator IEnumerable.GetEnumerator(){返回GetEnumerator();}
}
编译器将使用单独的枚举器创建正确的设备来实现这一点

除非您是为.NET1.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; }
    } 
}
T类:IEnumerable
{
公共T(){}
公共IEnumerator GetEnumerator(){返回新的TEnumerator();}
IEnumerator IEnumerable.GetEnumerator(){返回GetEnumerator();}
私有类定义器:IEnumerator
{
私有整数位置=-1;
公共int当前{get{return position;}}
对象IEnumerator.Current{get{return Current;}}
void IDisposable.Dispose(){}
公共图书馆
{
位置++;
返回(位置<5);
}
public void Reset(){position=-1;}
} 
}
这里的意义在于
TEnumerator
的不同实例允许相同的
T
实例分别迭代

foreach (int i in t)
   if (i == 2)
     foreach (int p in t)
       //print p
   else
       //print i
首先,一定要使用大括号,当你缩进匹配另一个
将要发生的事情时,如果在那里将混淆事情

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

但问题是:每个
T
实例只有一个计数器,并且使用的是同一个实例。所以你只需要做一次。如果要允许并发枚举,则需要将枚举器对象与每次返回新实例的
GetEnumerator
分开。

@Praetor12是,但需要第二种类型来表示枚举器。我来模拟一下。。。2秒。看起来这比我预期的要难一些,但这正是我所需要的。非常感谢@出于病态的好奇,你为什么要用这种方法来编写枚举器?我喜欢编写我理解的代码。我不知道yeild到底是如何工作的:(仅此而已。@Praetor12您可能会喜欢Raymond Chen的博客帖子,更具体地说,只是作为旁注进行链接:显示当前实现错误的另一种方式:
Console.WriteLine(t.Count());//5 Console.WriteLine(t.Count());//0
即,它当前只会迭代一次(请注意,
Reset()
永远不应该被使用-它被正式弃用,并且在大多数情况下会故意抛出异常)
foreach (int i in t) {
   if (i == 2) {
     foreach (int p in t) {
       //print p
      }
   } else {
       //print i
   }
 }