2009-05-19 56 views
1

假設我有一個IEnumerable,比如一個List(TValue),並且我想跟蹤這個列表是否被訪問(爲了防止問題發生,例如,當它在另一個線程上迭代時添加到列表中) ;我總是可以寫代碼如下所示:有沒有辦法檢查IEnumerable是否使用For Each循環訪問?

Dim List1 As New List(Of Integer) 
Dim IteratingList1 As Boolean = False 

' ... some code ... ' 

Private Function getSumOfPositivesFromList1() As Integer 
    If IteratingList1 Then Return -1 

    IteratingList1 = True 

    Dim SumOfPositives As Integer = 0 

    For Each x As Integer In List1 
     If x > 0 Then SumOfPositives += x 
    Next 

    IteratingList1 = False 

    Return SumOfPositives 
End Function 

(我知道這個代碼是很隨意的,但是它說明了什麼我說的。)

我的問題是,是否有一個更好/更清潔方法來執行此檢查比手動更新和訪問布爾,如上所述。我覺得肯定有,但據我所知,沒有任何IEnumerable類具有內置的「我正在迭代」方法或屬性。而寫一個實現IEnumerable幷包含這樣一個屬性的新類似乎對我來說過分了。

回答

3

Afaik,在VB.NET中,您可以使用SyncLock在訪問對象時鎖定對象,以防止其他線程同時對其進行操作。

Public Shared objStorageLock As New Object 

Private Function getSumOfPositivesFromList1() As Integer 

    Dim SumOfPositives As Integer = 0 

    SyncLock objStorageLock 

    For Each x As Integer In List1 
     If x > 0 Then SumOfPositives += x 
    Next 

    End SyncLock 

    Return SumOfPositives 
End Function 
+0

謝謝!我以前不熟悉SyncLock。現在出於好奇,在這種情況下,爲什麼我會創建這個新的objStorageLock對象,而不是簡單地編寫「SyncLock List1 ... End SyncLock」? – 2009-05-19 14:01:41

1

這取決於你在做什麼,如果你擔心到列表Synclock多寫訪問的路要走。

如果你是枚舉過程中消除異常之後,那麼它有時好做得到一份拷貝和枚舉如

For Each Num as Integer in SumOfPositives.ToArray() 
... 
Next Num 

顯然,你可能要考慮你的內存使用情況和性能等等,等等,但一般這工作得很好,而且速度很快。

1

如果存在合適的函數,VB.net將使用GetEnumerator函數,而不是使用IEnumerable接口。因此可以實現IEnumerable但調用實現IEnumerable.GetEnumerator一些其他名稱的方法。因爲大多數枚舉某些東西的枚舉將使用IEnumerable而不是鴨子輸入的GetEnumerator,所以GetEnumerator方法本身被調用的事實表明它正被for-each循環所使用。