2009-07-06 49 views
22

我正在瀏覽IEnumerable和IEnumerator,但無法清楚地得到一點。如果我們有foreach,那麼爲什麼我們需要這兩個接口?有沒有我們必須使用接口的場景。如果是,那麼有人可以用一個例子來解釋。 歡迎任何建議和評論。 謝謝。IEnumerable,IEnumerator與foreach,何時使用什麼

回答

46

foreach使用接口在許多情況下。如果你想實現那麼你需要這些接口,然後foreach可以使用。 (雖然迭代器塊通常使這個實現任務非常簡單)。

但是,只是偶爾直接使用迭代器會很有用。一個很好的例子是當試圖「配對」兩個不同的序列時。例如,假設您收到兩個序列 - 名稱之一,年齡之一,並且您想將它們打印在一起。你可能會這樣寫:

static void PrintNamesAndAges(IEnumerable<string> names, IEnumerable<int> ages) 
{ 
    using (IEnumerator<int> ageIterator = ages.GetEnumerator()) 
    { 
     foreach (string name in names) 
     { 
      if (!ageIterator.MoveNext()) 
      { 
       throw new ArgumentException("Not enough ages"); 
      } 
      Console.WriteLine("{0} is {1} years old", name, ageIterator.Current); 
     } 
     if (ageIterator.MoveNext()) 
     { 
      throw new ArgumentException("Not enough names"); 
     } 

    } 
} 

同樣也可以是,如果你想治療(說)不同的使用迭代器的第一個項目到受用:

public T Max<T>(IEnumerable<T> items) 
{ 
    Comparer<T> comparer = Comparer<T>.Default; 

    using (IEnumerator<T> iterator = items.GetEnumerator()) 
    { 
     if (!iterator.MoveNext()) 
     { 
      throw new InvalidOperationException("No elements"); 
     } 
     T currentMax = iterator.Current; 

     // Now we've got an initial value, loop over the rest 
     while (iterator.MoveNext()) 
     { 
      T candidate = iterator.Current; 
      if (comparer.Compare(candidate, currentMax) > 0) 
      { 
       currentMax = candidate; 
      } 
     } 
     return currentMax; 
    } 
} 

現在,如果你對IEnumerator<T>IEnumerable<T>之間的區別感興趣,您可能想要用數據庫術語思考它:將IEnumerable<T>作爲表,將IEnumerator<T>作爲遊標。您可以請求一個表給您一個新的遊標,並且您可以同時在同一個表上有多個遊標。

可能需要一段時間才能真正理解這種差異,但只要記住一個列表(或數組,或其他)沒有任何「你在列表中的位置」的概念,而是在列表/ array/whatever does有那麼點的狀態是有幫助的。

+0

感謝喬恩爲你提供的所有幫助。我現在明白了,並且將會學習更多,以便說清楚。 另外我發現下面的鏈接非常有用: http://stackoverflow.com/questions/558304/can-anyone-explain-ienumerable-and-ienumerator-to-me – Wondering 2009-07-06 07:12:43

+0

這是一個例子,你堅持使用IEnumerator只是保持高效。 http://stackoverflow.com/questions/1018407/what-is-the-most-elegant-way-to-get-a-set-of-items-by-index-from-a-collection/1025137#1025137 – 2009-07-06 11:59:04

+0

@Jon Skeet我真的很喜歡你編碼方式Max 的方法。我有一個問題。你使用IEnumberator構造。我知道使用處理它裏面的東西()。你爲什麼在IEnumberator上使用它? – 2012-05-29 05:47:38

8

喬恩說什麼。

  • IEnumerableIEnumerable<T>:通過實施此對象指出,它可以給你,你可以用它來遍歷在序列/集合的迭代器/集
  • IEnumeratorIEnumerator<T>:如果你調用定義GetEnumerator方法在前一個界面中,您將獲得一個迭代器對象作爲IEnumerator引用。這使您可以調用MoveNext()並獲取當前對象。
  • foreach:從某種意義上說,它是C#構造/外觀,因爲您不需要知道它如何在引擎蓋下工作。它在內部獲取迭代器併爲您調用正確的方法專注於您想要對每個項目執行的操作(foreach塊的內容)。大多數情況下,除非實現自己的類型或自定義迭代,否則只需要foreach,在這種情況下,您需要了解前2個接口。
6

記住,你不來實現IEnumerator及其一些變體使用的foreach - IIRC,它需要一切是返回具有的MoveNext()方法返回一個對象的GetEnumerator()方法一個bool和一個Current屬性返回一個對象。您不需要使用IEnumerator和IEnumerable,但通常這是一個非常好的主意。有關更多信息,請參閱here

相關問題