2013-10-28 73 views
4

考慮文檔IEnumerator.Current迭代器塊的編譯器實現不正確?

目前還拋出一個異常,如果對MoveNext的上一次調用返回 假的,這表明了集合的末尾

然而,這不符合迭代器發生塊。例如:

void Main() 
{ 
    using (var enumerator = GetCounter().GetEnumerator()) 
    { 
     for (int i = 0; i < 10; i++) 
     { 
      enumerator.MoveNext(); 
      Console.WriteLine (enumerator.Current); 
     } 
    } 
} 

static IEnumerable<int> GetCounter() 
{ 
    for (int count = 0; count < 3; count++) 
    { 
     yield return count; 
    } 
} 

只會打印8次2,沒有異常拋出。看着compiler transformation,Current只是一個字段支持的屬性,它總是返回字段的值,僅此而已。也許這是某種形式的優化?但是,這看起來像違反了合同。

+0

哦,我錯過了!顯然它被改爲「未定義」。我想這回答我的問題,但我不能接受評論,所以請讓它成爲答案。 –

+0

你可以回答你自己的問題。 –

回答

4

儘管對於IEnumerator.Current的文檔是正確的,IEnumerator<T>.Current's documentation指出該屬性未定義爲這種情況。用你的迭代器,它返回「2」。 List<T>的調查員返回default(T),並T[]的引發異常。這些都是有效的實現,因爲它是未定義的。

電流在任何下列條件未定義:

  • 枚舉定位集合中的第一個元素之前,創建枚舉之後立即。在讀取當前值之前,必須調用MoveNext以使枚舉器前進到集合的第一個元素。
  • MoveNext的最後一次調用返回false,表示收集結束。
  • 枚舉器因集合中的更改而失效,如添加,修改或刪除元素。

值得一提的是,儘管它實現了接口,從yield return生成的代碼不正確執行IEnumerator,因爲它繼續在這種情況下返回2

IEnumerator enumerator = GetCounter().GetEnumerator(); 
for (int i = 0; i < 10; i++) 
{ 
    enumerator.MoveNext(); 
    Console.WriteLine (enumerator.Current); 
} 

(作爲比較,List<T>是否正確:如果在結束後得到IEnumerator.Current,則會引發異常,並且如果在結束後調用IEnumerator<T>.Current,則返回default(T)

+0

+1,但我們又回到了sqaure,不是嗎? 'IEnumerator'沒有正確實現,或許我應該提交一個連接錯誤? –

+0

@OhadSchneider是的,你是對的。這當然是一個小錯誤,但它是一個錯誤。 –

+0

好吧,我在這裏提交了一個bug:https://connect.microsoft.com/VisualStudio/feedback/details/806924/iterator-blocks-are-not-implemented-according-to-documentation –