36

電話をかける正しい方法はどれくらい正確IEnumerator.Resetですか?

ドキュメントには次のように書かれています。

このResetメソッドは、COMの相互運用性のために提供されています。必ずしも実装する必要はありません。代わりに、実装者は単に。をスローできますNotSupportedException

さて、それは私がそれを呼ぶことになっていないという意味ですか?

フロー制御に例外を使用するのはとても魅力的です。

using (enumerator = GetSomeExpensiveEnumerator())
{
    while (enumerator.MoveNext()) { ... }

    try { enumerator.Reset(); } //Try an inexpensive method
    catch (NotSupportedException)
    { enumerator = GetSomeExpensiveEnumerator(); } //Fine, get another one

    while (enumerator.MoveNext()) { ... }
}

それは私たちがそれを使用することになっている方法ですか?それとも、マネージコードから使用するつもりはありませんか?

4

3 に答える 3

57

決して; 最終的にこれは間違いでした。シーケンスを複数回繰り返す正しい方法は、もう一度呼び出す.GetEnumerator()つまり、foreachもう一度使用します。データが再現できない(または繰り返すのに費用がかかる)場合は、.ToList()または同様の方法でデータをバッファリングします。

イテレータブロックがこのメソッドの例外をスローすることは、言語仕様の正式な要件です。そのため、動作することを信頼することはできません。これまで。

于 2011-05-11T18:38:17.453 に答える
8

使用しないことをお勧めします。最新の実装の多くはIEnumerable、例外をスローするだけです。

列挙子を取得することは、「高価」になることはほとんどありません。高価になる可能性のあるものすべてを(完全に)列挙しています。

于 2011-05-11T18:35:00.070 に答える
0
public class PeopleEnum : IEnumerator
{
    public Person[] _people;

    // Enumerators are positioned before the first element 
    // until the first MoveNext() call. 
    int position = -1;

    public PeopleEnum(Person[] list)
    {
        _people = list;
    }

    public bool MoveNext()
    {
        position++;
        return (position < _people.Length);
    }

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

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

    public Person Current
    {
        get
        {
            try
            {
                return _people[position];
            }
            catch (IndexOutOfRangeException)
            {
                throw new InvalidOperationException();
            }
        }
    }
}
于 2014-04-29T10:50:45.403 に答える