2011-12-02 90 views
5

它看起來像將列表的枚舉器傳遞給函數「byval」與將它傳遞給「byref」完全不同。實質上,即使函數使枚舉器前進,常規的「byval」傳遞也不會改變調用者的「enumerator.Current值」。我想知道是否有人知道這是爲什麼?枚舉器是一個像整數一樣的原始類型,沒有對象引用,因此對其的更改不會反映到調用方中?將列表的枚舉器傳遞給一個函數

下面是示例代碼:

此功能BYVAL,並卡在一個無限循環,隨地吐痰「1」的消息框,因爲枚舉的「當前」永遠前進經過5:

Public Sub listItemsUsingByValFunction() 
    Dim list As New List(Of Integer)(New Integer() {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) 

    Dim enumerator = list.GetEnumerator() 
    enumerator.MoveNext() 
    While enumerator.Current <= 5 
     listFirstItemByVal(enumerator) 
    End While 
End Sub 
Private Sub listFirstItemByVal(ByVal enumerator As List(Of Integer).Enumerator) 
    MsgBox(enumerator.Current) 
    enumerator.MoveNext() 
End Sub 

此,在另一方面,工作只是正如人們所預料:

Public Sub listItemsUsingByRefFunction() 
    Dim list As New List(Of Integer)(New Integer() {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) 

    Dim enumerator = list.GetEnumerator() 
    enumerator.MoveNext() 
    While enumerator.Current <= 5 
     listFirstItemByRef(enumerator) 
    End While 
End Sub 
Private Sub listFirstItemByRef(ByRef enumerator As List(Of Integer).Enumerator) 
    MsgBox(enumerator.Current) 
    enumerator.MoveNext() 
End Sub 

兩個函數之間的區別是listFirstItem__功能只有是否接受byval或byref枚舉器。

回答

8

您看到此行爲的原因是List(Of T).EnumeratorStruct而不是Class,正如通常所預期的那樣。因此,當您通過枚舉器時,您傳遞它的一個副本,因此只有在您致電MoveNext

+0

有趣!謝謝你澄清這一點! –

+0

因此,如果您將統計員傳遞給函數,您是否總是使用「byref」做一個心理註釋?例如,是否有一些解決方法可以避免永遠記住這一點,尤其是因爲Visual Studio會自動生成總是使用byval的方法,所以這樣的事情可能很容易被忽視? –

+0

@MichaelZlatkovsky如果使用最常見的「IEnumerator(Of T)」,則不需要這樣做。每當我通過一個類型特定的枚舉器時,我總是在做'ByVal'之前檢查類型與'ByRef' – JaredPar

0

時纔會更新該副本,因此使用所提供的示例代碼將無法使用Option Strict On進行編譯。修復可能會解決你看到的差異。

Public Sub listItemsUsingByValFunction() 
    Dim list As New List(Of Integer)(New Integer() {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) 

    Dim enumerator As IEnumerator(Of Integer) = list.GetEnumerator() 
    enumerator.MoveNext() 
    Debug.WriteLine("S " & enumerator.Current) 
    Stop 
    Do 
     Debug.WriteLine("W " & enumerator.Current) 
     If Not listFirstItemByVal(enumerator) Then Exit Do 
    Loop 
End Sub 

Private Function listFirstItemByVal(ByVal enumerator As IEnumerator(Of Integer)) As Boolean 
    Debug.WriteLine("F " & enumerator.Current) 
    Return enumerator.MoveNext() 
End Function 

Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click 
    listItemsUsingByValFunction() 
End Sub 
+0

真的嗎?我將「Option Strict On」添加到了我的原始代碼中,但仍然沒有任何警告或錯誤。 –

+1

我應該說,Option Strict On,Option Infer Off,Option Explicit On。抱歉。 – dbasnett

+0

呵呵,我沒有意識到,轉身推斷會發現其他方面沒有顯示的錯誤(當我第一次設置我的項目時,我認爲越多的東西都是「開」,越好越好)。您認爲最佳做法?是否需要更多打字 - 例如,它是否值得您購買? –