的GetEnumerator()的推荐行为实施了IEnumerable&LT时,T>和IEnumerator的< T>行为、IEnumerable、GetEnumerator、IEn

2023-09-04 02:42:32 作者:我的世界就缺你

我实现我自己的枚举类型。事情ressembling这样的:

I am implementing my own enumerable type. Something ressembling this:

public class LineReaderEnumerable : IEnumerable<string>, IDisposable
{
    private readonly LineEnumerator enumerator;

    public LineReaderEnumerable(FileStream fileStream)
    {
        enumerator = new LineEnumerator(new StreamReader(fileStream, Encoding.Default));
    }

    public IEnumerator<string> GetEnumerator()
    {
        return enumerator;
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }

    public void Dispose()
    {
       enumerator.Dispose();
    }
}

枚举器类:

public class LineEnumerator : IEnumerator<string>
{
    private readonly StreamReader reader;
    private string current;

    public LineEnumerator(StreamReader reader)
    {
        this.reader = reader;
    }

    public void Dispose()
    {
        reader.Dispose();
    }

    public bool MoveNext()
    {
        if (reader.EndOfStream)
        {
            return false;
        }
        current = reader.ReadLine();
        return true;
    }

    public void Reset()
    {
        reader.DiscardBufferedData();
        reader.BaseStream.Seek(0, SeekOrigin.Begin);
        reader.BaseStream.Position = 0;
    }

    public string Current
    {
        get { return current; }
    }

    object IEnumerator.Current
    {
        get { return Current; }
    }
}

我的问题是:我应该叫复位()在枚举时的GetEnumerator()被调用或者是它的调用方法(如的foreach)的责任去做

My question is this: should I call Reset() on the enumerator when GetEnumerator() is called or is it the responsability of the calling method (like foreach) to do it?

应该的GetEnumerator()创建一个新的,还是它应该总是返回同一个实例?

Should GetEnumerator() create a new one, or is it supposed to always return the same instance?

推荐答案

你的类型的用户的期望将是的GetEnumerator()返回一个新的枚举器对象。

The expectation of a user of your type would be that GetEnumerator() returns a new enumerator object.

当你定义它每次调用的GetEnumerator 返回相同的枚举,因此code这样的:

As you have defined it every call to GetEnumerator returns the same enumerator, so code like:

var e1 = instance.GetEnumerator();
e1.MoveNext();
var first = e1.Value();

var e2 = instance.GetEnumerator();
e2.MoveNext();
var firstAgain = e2.Value();

Debug.Assert(first == firstAgain);

如预期

将无法正常工作。

will not work as expected.

(在内部调用重置将是一个不寻常的设计,但这是次要位置。)

(An internal call to Reset would be an unusual design, but that's secondary here.)

其他:的 PS 如果你想要一个枚举器文件的行再使用的 File.ReadLines ,但它似乎(见Jon飞碟双向的回答)这个患有同样的问题,因为你的code。

Additional: PS If you want an enumerator over the lines of a file then use File.ReadLines, but it appears (see comments on Jon Skeet's answer) this suffers from the same problem as your code.