Übergeben des Enumerators einer Liste an eine Funktion
-
27-10-2019 - |
Frage
Es sieht so aus, als würde man den Aufzähler einer Liste an eine Funktion "Byval" übergeben, ist ganz anders als "Byref". Im Wesentlichen ändert das regelmäßige "Byval" -Passer nicht den "Enumerator.Current Value" des Anrufers, selbst wenn die Funktion den Enumerator voranschreitet. Ich habe mich gefragt, ob jemand weiß, warum dies der Fall ist. Ist ein Enumerator ein Primitiv wie eine Ganzzahl ohne Objektreferenz, und daher wird sich im Anrufer nicht reflektiert?
Hier ist der Beispielcode:
Diese Funktion ist byval und steckt in einer unendlichen Schleife stecken und spuckt "1" -Beachboxen aus, da der "aktuelle" des Enumerators nie nach 5 vorbringt:
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
Dies hingegen funktioniert genauso wie man erwarten würde:
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
Der Unterschied zwischen den beiden Funktionen besteht nur darin, ob die ListFirstitem__ -Funktion einen Byval oder einen ByRef -Enumerator akzeptiert.
Lösung
Der Grund, warum Sie dieses Verhalten sehen, ist das List(Of T).Enumerator
ist ein Struct
und nicht a Class
Wie allgemein erwartet. Wenn Sie also den Enumerator übergeben, passieren Sie eine Kopie davon und daher wird nur diese Kopie aktualisiert, wenn Sie anrufen MoveNext
Andere Tipps
Die Verwendung des angegebenen Beispielcodes würde nicht mit der Option strikt kompilieren. Behebung, die den von Ihnen angezeigten Unterschied beheben kann.
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