VisualBasic Dictionary ByVal/ByRef

Gilrich

Cadet 4th Year
Registriert
Nov. 2009
Beiträge
96
Hallo
Mir ist grad aufgefallen, dass es anscheinend keinen Unterschied macht, ob ich ein Dictionary mit ByVal oder ByRef an eine Prozedur übergebe.

Code:
Module Module1

    Sub Main()
        Dim dict As New Dictionary(Of String, Integer)
        dict.Add("a", 23)
        test(dict)
        MsgBox(dict.Count)
    End Sub

    Sub test(ByVal dictionary As Dictionary(Of String, Integer))
        dictionary.Clear()
        MsgBox(dictionary.Count)
    End Sub
End Module

Dieser Code ergibt die Ausgabe "0" , "0" egal ob ich ByVal oder ByRef schreibe.
Ist das normal so, oder hab ich irgendwo ein Überlegungsfehler?

Danke für die Auskunft.
Gruss Gil
 
"dictionary" selbst ist ja eine Referenz auf ein Objekt, daher macht es hier keinen Unterschied.
Wenn du jedoch in der "test" Methode "dictionary" durch ein anderes Objekt ersetzt, solltest du einen Unterschied merken. Also "dictionary = new Dictionary()" oder wie auch immer das in VB.Net genau geht.
 
So machts zwar einen Unterschied, aber wenn ich ein neues Objekt erstelle, dann ist "Dictionary" nacher leer.
Dann nützt mir das übergeben ja überhaupt nichts. Ich will ja, dass "Dictionary" die Werte von "Dict" enthält.
 
Das verstehe ich nicht. "dictionary" enthält doch die Werte von "dict". Nur da du "dictionary.Clear()" aufrufst, werden sie natürlich gelöscht.
 
Vielleicht hab ich dich einfach falsch verstanden.
Ich hab den Code jetzt mal umgeschrieben.

Code:
 Sub Main()
        Dim dict As New Dictionary(Of String, Integer)
        dict.Add("a", 1)
        test(dict)
        MsgBox(dict.Count)
    End Sub

    Sub test(ByVal dictionary As Dictionary(Of String, Integer))
        dictionary = New Dictionary(Of String, Integer)

        dictionary.Add("b", 2)
        MsgBox(dictionary.Count)
    End Sub

Hier erhalte ich die Ausgabe "1", "1" . Denn nach der Zeile " dictionary = New Dictionary(Of String, Integer)" enthält "dictionary" die Werte von "dict" nicht mehr.
Lass ich diese Zeile aber weg, dann erhalte ich "2","2" als Ausgabe obwohl ich eigentlich "2", "1" erwarten würde. (Da ja mit ByVal "dict" nicht verändert werden sollte)

Ich hoffe man versteht was ich meine.
 
"2" und "2" ist schon richtig. Denn du übergibst der "test"-Funktion ja nur eine Referenz auf das Objekt. Ob die Referenz nun als Value oder selbst als Referenz übergeben wird, spielt in der Hinsicht keine Rolle.
Beide Funktionen greifen letztenendes auf dasselbe Objekt zu.
"2" und "1" würdest du bekommen, wenn du der "test"-Funktion eine Kopie des Objektes übergeben würdest.

Falls dich das alles noch verwirrt, kannst du anstelle von einem Dictionary erstmal ein "int" nehmen. Da wird es klarer, wo der Unterschied zwischen Val und Ref liegt.
 
Was mich verwirrt ist, dass es eben mit "int" so funktioniert wie ich das möchte. Nur eben mit dem "Dictionary" nicht. Ich dachte mit ByVal wird eine Kopie erstellt und mit ByRef eine Referenz.
 
Mit ByVal wird eine Kopie von der Referenz erstellt, nicht vom Objekt selbst. Bei ints hingegen wird der int selbst kopiert, da ints keine Objekte sind.
Betrachte es mal aus einem anderen Winkel. Wenn du nur einmal "new Dictionary" aufrufst, existiert ja nur 1 Dict. Es müssen also folglich beide Funktionen mit demselben Objekt arbeiten. Lösen kannst du das, indem du das Objekt selbst kopierst. Ich glaube es gibt da eine Copy() Methode.
 
Achso, jetzt hab ichs kapiert. :D
Danke für die Geduld!
 
Die beste Erklärung die ich gefunden habe:

ByRef schrieb:
...Wenn Sie allerdings wünschen, dass es solche Rückwirkungen gibt, dann
müssen Sie vor der betreffenden Variablen das Schlüsselwort ByRef (statt
ByVal) einfügen. Dies bedeutet, dass eine Referenz auf die Original-Variable
an die Prozedur (oder Funktion) übergeben wird. Über diese Referenz
kann die Original-Variable verändert werden...
Public Class Form1
Private Sub cmdKopie_Click(...) Handles ...
Dim x, y As Integer
x = 5
y = 12
lblAnzeige.Text = "Vorher: x: " & x &
", y: " & y
TauscheKopie(x, y)
lblAnzeige.Text &= vbCrLf &
"Nachher: x: " & x & ", y: " & y
End Sub
Private Sub cmdReferenz_Click(...) Handles ...
Dim x, y As Integer
x = 5
y = 12
lblAnzeige.Text = "Vorher: x: " & x &
", y: " & y
TauscheReferenz(x, y)
lblAnzeige.Text &= vbCrLf &
"Nachher: x: " & x & ", y: " & y
End Sub
Sub TauscheKopie(ByVal a As Integer,
ByVal b As Integer)
Dim c As Integer
c = a
a = b
b = c
End Sub
Sub TauscheReferenz(ByRef a As Integer,
ByRef b As Integer)
Dim c As Integer
c = a
a = b
b = c
End Sub
End Class
Buch:
Titel "Einstieg in Visual Basic 2010 2. Auflage (2010)"
Erschienen im Galileo Verlag
Kapitel 4.8.2, Seite 156 f.
Will ja hier nicht meinen Postertitel verlieren, weil ich "klaue". :D
Also bei ByVal wird eine Kopie gefertigt und mit der Kopie weiter gearbeitet in der neuen Prozedur ohne dass es eine Wirkung auf die Originalvariable hat, mit byRef wird auch eine Kopie gefertigt und gearbeitet in der neuen Prozedur und sollte sich die Kopie ändern, ändert sich auch die Originalvariable mit.
 
Zuletzt bearbeitet:
Als grobe Erklärung mag dies ausreichen, allerdings kann man damit schnell auf die Nase fallen. In Java werden z.B. übergebene Objekte auch im Original verändert, obwohl es in Java kein Call by Reference gibt (es ist alles Call by Value). Was kopiert wird ist nämlich die Referenz (nicht das Objekt selbst) auf das tatsächliche Objekt, und aufgrund der Änderungen am Original könnte man zu dem Entschluss kommen, es handle sich um Call by Reference - was aber nicht so ist.
 
Da ja zum einem im Thementitel schon stand "VisualBasic" und im Buchtitel genauso "Einstieg in Visual Basic 2010" die Programmiersprache höchst genau beschrieben wird, denk ich mal, reicht es als Erklärung. Wenn man die Programmiersprache dann ändert, ja dann können dafür wieder andere Regeln gelten.
 

Ähnliche Themen

Zurück
Oben