Visual Basic - Technik, FAQ, Tricks, Beispiele

Home / Allgemein / Entwicklung / ByVal

ByVal oder ByRef - Parameter richtig deklarieren

Einleitung

Die Erstellung von Prozeduren (egal ob Function, Sub, Property oder Methode genannt) ist das A und O der Software-Entwicklung. Nur durch Prozeduren kann eine strukturierte Programmierung erfolgen, so dass auch nicht-triviale Projekte zu einem erfolgreichen Ende geführt werden können.

Schauen wir uns mal folgendes Beispiel einer Funktions-Deklaration an:

Function Plus1(n As Long) As Long
  n = n + 1
  Plus1 = n
End Function

Sub Test
  Dim x As Long

  x = 50
  MsgBox "1: " & Plus1(x)
  MsgBox "2: " & Plus1(x)
  MsgBox "x: " & x
End Sub

Wenn die Test-Prozedur aufgerufen wird, so wird erst "51" ausgegeben, dann "52". x hat abschließend den Wert "52" gespeichert. Obwohl n nur in der Funktion erhöht wird, hat die Zuweisung offensichtlich Auswirkungen auf x! Hätten Sie das erwartet?

Um dies zu verstehen, muss man wissen, dass VB zwei verschiedene Arten von Parameter-Übergaben kennt, "By Reference" und "By Value":

ByRef-Parameter

Eine Parameter-Übergabe "By Reference" bedeutet, dass die Adresse der übergebenen Variable an die Prozedur übergeben wird. Die Prozedur kann dadurch auf den Originalwert der Variable operieren, und daher auch den Inhalt ändern.

Gekennzeichnet wird ein solcher Parameter durch das Schlüsselwort ByRef. Bis einschließlich VB6 ist dies übrigens die Default-Methode der Parameter-Übergabe, daher kann die Deklaration aus obigem Beispiel auch so geschrieben werden:

Function Plus1(ByRef n As Long) As Long

Ich empfehle dringend, dieses Schlüsselwort zu nutzen. Einerseits wird die Art der Parameter-Übergabe besser Dokumentiert, d.h. der Anwender der Prozedur ist "vorgewarnt", dass sich eventuell die Inhalte seiner Parameter-Variablen ändern können. Andererseits wird ab VB7 (VB.NET) die Default-Methode "By Value" sein!

Wichtiger Hinweis: Da bei Nutzung von "By Reference" nur Adressen bewegt werden, müssen die Datentypen der Übergabe-Variablen und des Parameters exakt übereinstimmen. Dies wird von VB streng kontrolliert (Fehlermeldung 13, "Type mismatch") und zwar vor dem Aufruf, da ansonsten "Allgemeine Schutzverletzungen" die Folge wären (Weitere Gründe für Variablen-Deklarationen: "Pfui oder Hui? - Schöner programmieren!").

ByVal-Parameter

Bei einer "By Value" Parameter-Übergabe erzeugt VB erst eine komplette Kopie des Parameter-Werts. Die Prozedur operiert also immer auf eine Kopie des Parameters, der Originalwert der Variablen ist also sicher vor Veränderungen.

Gekennzeichnet wird ein solcher Parameter durch das Schlüsselwort ByVal. Ändern wir die obige Parameter-Deklaration auf "By Value", also

Function Plus1(ByVal n As Long) As Long

dann wird bei Aufruf der Test-Prozedur zweimal der Wert "51" ausgegeben. Die Variable x hat zum Schluss immer noch "50" gespeichert.

Wichtiger Hinweis: Objekt-Variablen enthalten intern sowieso nur einen Zeiger auf das Objekt. Daher ist es egal, welche Methode hier zur Parameter-Übergabe verwendet wird: Die Eigenschaften des Objekts sind in der Prozedur immer änderbar.

Tipps zur Verwendung

Da ByVal erst eine Kopie der Parameter macht, ist diese Methode sicher vor unerwünschten Nebenwirkungen. Allerdings kostet das Kopieren Zeit, insbesondere bei umfangreichen Parametern (z.B. langen Strings). Daher empfehle ich die Nutzung von ByRef aus folgenden Gründen:

Die Nutzung von ByRef zur Beschleunigung der Parameter-Übergabe bei einfachen Datentypen wie z.B. Long ist sinnlos, da in diesen Fällen die Kopie (hier 4 Bytes) nicht größer ist, als die zu bewegende Adresse (immer 4 Bytes)! Dieses gilt im Wesentlichen auch für die anderen Datentypen (Integer, Single, ...).

Hinweis: Sie können einen "By Reference"-Parameter beim Aufruf durch einfache Klammerung der zu übergebenen Variable in einen "By Value"-Parameter umwandeln. Im folgenden Beispiel ist x sicher vor jeder Veränderung, d.h. egal wie die Funktions-Parameter deklariert sind, der Aufruf verhält sich wie bei ByVal:

x = 50
MsgBox "1: " & Plus1((x))
MsgBox "2: " & Plus1((x))
MsgBox "x: " & x 'immer noch 50

Dies hilft übrigens auch, wenn der Datentyp nicht übereinstimmt, da VB dann eine automatische Typ-Umwandlung vornimmt (ähnlich wie bei einer Zuweisung).

© Jost Schwider, 23.04.2001-23.04.2001 - http://vb-tec.de/byvalref.htm