2016-11-23 23 views
0

我在圖形庫中的下面的代碼:IEnumerator的<T> .Current超越的MoveNext()==假

while(true) { 
    using (var i = ancestry.GetAdjacent(current).GetEnumerator()) 
    { 
     if (!i.MoveNext()) 
      yield break; 

     if (i.MoveNext()) 
      throw new InvalidOperationException("ancestry graph can only have one adjacent vertex for any given vertex"); 
     // it's a bug, as some enumerators could return null after failed MoveNext(). 
     current = i.Current; 
     if (isSentinel(current)) 
      yield break; 
    } 
} 

此代碼爲IEnumerator的一些情況,並從別人失敗(所有標準的實現。 NET,加上迭代方法與產量的回報。

是該行爲未指定的?

如果沒有,什麼是正確的符號?留在目前的前面,或者設置爲默認(T)?

更新:

我已經探索了IEnumerator的集合,Linq擴展以及鍵入數組的一些實現:fiddle

根據我的理解,Linq違反IEnumerable的合約,因爲它不會在枚舉結束時拋出Current,並且鍵入的數組違反IEnumerable的合約,因爲它在IEnumerable<T>.Current上拋出,並且沒有指定異常類型爲IEnumerable.Current。

有人可以澄清,它是什麼意思'未定義',當它在文檔中說明?是否包括拋出未指定的異常:

IEnumerator.Current Property文檔:

目前正在下列任一條件未定義:該 枚舉數定位在集合中第一個元素之前, 後立即枚舉器已創建。在讀取當前值之前,MoveNext必須被調用 以使枚舉器前進到集合 的第一個元素。 MoveNext 的最後一次調用返回false,表示集合的結束。 枚舉器由於集合中的更改而失效,例如 與添加,修改或刪除元素相關。在調用MoveNext之前,Current返回相同的 對象。 MoveNext將當前設置爲下一個 元素。

回答

3

沒有定義的Current的值,如果MoveNext返回false,按照接口的合同,作爲其文件中有描述。你不應該依賴任何給定的行爲。只要MoveNextfalse,您根本不應該檢查Current的值。

如果MoveNext越過集合的末尾,枚舉被收集和MoveNext返回false中的最後一個元素之後。當調查員在此位置時,對MoveNext的後續調用也會返回false。如果最後致電MoveNext返回false,則Current未定義。

(注:IEnumeratorCurrent應該扔在這種情況下的例外,但在我的經驗,大多數實現也懶得顯式地拋出,他們只是露出一個未定義的值;這種變化反映在新IEnumerator<T>界面的文檔)。