2009-05-19 31 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循环所使用。

相关问题