2

MSDN のこの例で、GetEnumeratorメソッド内でPeopleEnumが返されるのはなぜIEnumeratorですか?

public class Person
{
    public Person(string fName, string lName)
    {
        this.firstName = fName;
        this.lastName = lName;
    }

    public string firstName;
    public string lastName;
}

public class People : IEnumerable
{
    private Person[] _people;
    public People(Person[] pArray)
    {
        _people = new Person[pArray.Length];

        for (int i = 0; i < pArray.Length; i++)
        {
            _people[i] = pArray[i];
        }
    }
   //why??? 
   IEnumerator IEnumerable.GetEnumerator()
   {
       return (IEnumerator) GetEnumerator();
   }

   public PeopleEnum GetEnumerator()
   {
       return new PeopleEnum(_people);
   }
}

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

更新: ところで、配列データ型が ICloneable インターフェイスを実装している場合、msdn が for ループを記述して pArray を _people にコピーしたのはなぜですか?

4

2 に答える 2

3

インターフェイスを適切に実装するには、正確 に戻る必要があります。「明示的なインターフェイスの実装」を使用してこれを行っているため、パブリックAPI では が表示されますが、それでも満足していますIEnumeratorIEnumerablePeopleEnumIEnumerable

しかし実際には、C# 2.0 以降でこの方法で列挙子を記述することはほとんどありません。イテレータ ブロック ( ) を使用しますyield returnC# の詳細な第 6 章 (無料の章!) を参照してください。

PeopleEnum参考までに、ここに存在する理由は、これが .NET 1.1 のサンプルのように見えるためです。これが、型指定された列挙子を作成する唯一の方法です。.NET 2.0 以降ではIEnumerable<T>/IEnumerator<T>があり、これには型付き (ジェネリック経由) があり.Currentます。

.NET 2.0 / C# 2.0 (またはそれ以降) では、単純に次のようになります。

public class People : IEnumerable<Person> {
    /* snip */
    public IEnumerator<Person> GetEnumerator() {
        return ((IEnumerable<Person>)_people).GetEnumerator();
    }
    IEnumerator IEnumerable.GetEnumerator() { return _people.GetEnumerator();}
}
于 2010-04-14T06:14:13.887 に答える
2

IEnumerable を実装する型には、IEnumerator を返す GetEnumerator というメソッドが必要です。その例 (C# 2.0 ではかなり廃止されています) には、IEnumerator を実装する列挙子クラス PeopleEnum があります。これは、C# の foreach ステートメントによって内部的に使用されるものです。

より最新の例は、次のようになります。C# が反復子をサポートするようになったので、PeopleEnum クラスは不要になったことに注意してください。実質的に、コンパイラーが面倒な作業をすべて行ってくれます。

public class People : IEnumerable
{
    private Person[] _people;
    public People(Person[] pArray)
    {
        _people = new Person[pArray.Length];

        for (int i = 0; i < pArray.Length; i++)
        {
            _people[i] = pArray[i];
        }
    }

   IEnumerator IEnumerable.GetEnumerator()
   {
       for (int i=0; i < _people.Length; i++) {
           yield return _people[i];
       }
   }
}
于 2010-04-14T06:16:19.687 に答える