2009-10-03 127 views
2

說我有一個類實現IEnumerable<T>。它目前在GetEnumerator()方法中使用yield關鍵字。但現在我需要做更多,例如我想自己清理。要做到這一點,除非我忽略了任何事情,否則我需要實現IEnumerator<T>接口。但是你說我應該怎麼做?C#:在哪裏實現自定義IEnumerator <T>

該課程本身應該實施嗎GetEnumerator()返回this?或者將它隱藏在私人課堂會更好?或者它應該只是一個完全不同的課程?這有什麼常見的做法?

回答

6

如果您只需在枚舉器處理完成後清理一些資源(如foreach循環的末尾),那麼您可以使用所具有的功能來做到這一點,只需將try/finally塊添加到您的迭代器方法。

像這樣:

public IEnumerator<T> GetEnumerator() 
{ 
    try 
    { 
     // your iterator code here 
    } 
    finally 
    { 
     // cleanup code here 
    } 
} 

這一切就是這麼簡單。

+0

我以爲你不能在try塊內屈服? – 2009-10-03 13:29:29

+0

@ csharptest.net - 你可以,如果它只有一個finally塊之後。這是不允許的。 – 2009-10-03 13:34:21

+0

輝煌。不知道這甚至是可能的。經過測試後,'yield return'可以存在於try塊中。 *但是*它不能存在於'finally'塊中。而且,就像@Earwicker指出的那樣,它不能存在於有'catch'塊的'try'塊中。 – Svish 2009-10-03 13:39:41

2

我會去IEnumerator的一個類< T>。這將需要存儲不屬於集合的狀態(當前位置),而是枚舉過程的一部分。

+0

您可能想要閱讀「yield return」 - 它看起來像你寫了一個方法,但實際上你正在生成一個具有狀態的類。 – 2009-10-03 13:29:14

+0

@埃裏克,是的,我知道。所以這是我私人課堂建議的原因。因爲我猜想這樣會最終變得相似。雖然我沒有真正想到:p – Svish 2009-10-03 13:33:22

0

你可能不需要爲此編寫類。一個迭代器方法可以返回IEnumerable<T>,所以如果你的類只需要實現IEnumerable<T>而沒有別的,只需要爲整個事情寫一個迭代器方法。

如果沒有,你必須堅持與由具有迭代的方法做GetEnumerator實現IEnumerable<T>外部類,那麼你就沒有做任何事情很難迭代後清理。

IEnumerator<T>派生自IDisposable。迭代器方法通過執行finally塊或最後一個yield return之後的任何代碼來實現Dispose

+0

代碼在最後的收益率回報之後?這將如何工作?特別是如果「收益率回報」處於無限循環... – Svish 2009-10-03 14:17:03

+0

我已經說得很糟糕!最後一個「yield return」後面的代碼在可達時執行,但在最後一次調用「IEnumerator.MoveNext」時執行,而不是「Dispose」。如果收益回報處於無限循環中,那麼循環後面的代碼將無法訪問,編譯器會告訴您。如果不是,那麼在調用者枚舉集合中的所有項目後執行該代碼。因此,無論枚舉是完成還是放棄,都可以使用finally塊來執行,並且如果只有在枚舉未被放棄的情況下才需要執行,則可以將代碼放在方法的末尾。 – 2009-10-03 16:04:06