IEnumerable 和IEnumerator

一直以來,搞不懂IEnumerable與IEnumerator這兩個接口的區別,今天看了一下MSDN並在網上搜了一把關於他們的區別,似乎理解了,但還是弄不懂他們最主要的區別是什麼。看看MSDN是怎麼定義他們的吧。

public interface IEnumerable
 {
   IEnumerator GetEnumerator();
 }

 6public interface IEnumerator
 {
   bool MoveNext();
   void Reset();

   Object Current { get; }
}
 using System;
 using System.Collections;
 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];
        }
    }
   public IEnumerator 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;
   }
    public object Current
    {
        get
     {
      try
        {
               return _people[position];
            }
            catch (IndexOutOfRangeException)
        {
               throw new InvalidOperationException();
           }
       }
  }
}
class App
{
    static void Main()
    {
        Person[] peopleArray = new Person[3]
        {
            new Person("John", "Smith"),
            new Person("Jim", "Johnson"),
           new Person("Sue", "Rabon"),
        };
        People peopleList = new People(peopleArray);
        foreach (Person p in peopleList)
            Console.WriteLine(p.firstName + " " + p.lastName);
    }
}

最後看一段別人的總結,水平高的人應該理解更深吧。我先貼出來供以後參考。

1、一個Collection要支持foreach方式的遍歷,必須實現IEnumerable接口(亦即,必須以某種方式返回IEnumerator object)。
  2、IEnumerator object具體實現了iterator(通過MoveNext(),Reset(),Current)。
  3、從這兩個接口的用詞選擇上,也可以看出其不同:IEnumerable是一個聲明式的接口,聲明實現該接口的class是“可枚舉(enumerable)”的,但並沒有說明如何實現枚舉器(iterator);IEnumerator是一個實現式的接口,IEnumerator object就是一個iterator。
  4、IEnumerable和IEnumerator通過IEnumerable的GetEnumerator()方法建立了連接,client可以通過IEnumerable的GetEnumerator()得到IEnumerator object,在這個意義上,將GetEnumerator()看作IEnumerator object的factory method也未嘗不可。
  IEnumerator 是所有枚舉數的基接口。

枚舉數只允許讀取集合中的數據。枚舉數無法用於修改基礎集合。

最初,枚舉數被定位於集合中第一個元素的前面。Reset 也將枚舉數返回到此位置。在此位置,調用 Current 會引發異常。因此,在讀取 Current 的值之前,必須調用 MoveNext 將枚舉數提前到集合的第一個元素。

在調用 MoveNext 或 Reset 之前,Current 返回同一對象。MoveNext 將 Current 設置爲下一個元素。

在傳遞到集合的末尾之後,枚舉數放在集合中最後一個元素後面,且調用 MoveNext 會返回 false。如果最後一次調用 MoveNext 返回 false,則調用 Current 會引發異常。若要再次將 Current 設置爲集合的第一個元素,可以調用 Reset,然後再調用 MoveNext。

只要集合保持不變,枚舉數就將保持有效。如果對集合進行了更改(例如添加、修改或刪除元素),則該枚舉數將失效且不可恢復,並且下一次對 MoveNext 或 Reset 的調用將引發 InvalidOperationException。如果在 MoveNext 和 Current 之間修改集合,那麼即使枚舉數已經無效,Current 也將返回它所設置成的元素。

枚舉數沒有對集合的獨佔訪問權;因此,枚舉一個集合在本質上不是一個線程安全的過程。甚至在對集合進行同步處理時,其他線程仍可以修改該集合,這會導致枚舉數引發異常。若要在枚舉過程中保證線程安全,可以在整個枚舉過程中鎖定集合,或者捕捉由於其他線程進行的更改而引發的異常。

參考資料 http://www.cnblogs.com/illele/archive/2008/04/21/1164696.html

發佈了7 篇原創文章 · 獲贊 3 · 訪問量 2782
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章