Visual Basic .NET: Rückgabewerte

Funktionen dienen oft der Berechnung eines Wertes, zum Beispiel verfügt das .NET-Framework im Namespace System.Math über viele mathematische Funktionen für Logarithmen, Trigonometrie, etc. Diese Funktionen benötigen nicht nur bestimmte Werte, sondern liefern auch einen Wert zurück. Wie bei Operatoren auch heißt dieser Wert Rückgabewert.

An dieser Stelle geht Visual Basic einen anderen Weg als viele andere Programmiersprachen. In C etwa heißt eine Funktion immer „Funktion“. In Visual Basic heißt eine Funktion nur dann „Funktion“, wenn sie einen Rückgabewert hat. Eine Funktion ohne Rückgabewert heißt „Prozedur“. Eine Prozedur erkennt man am Schlüsselwort Sub nach Private in der ersten Zeile und nach End in der letzten Zeile. In Funktionen steht nicht Sub, sondern Function. (Sub kommt übrigens vom englischen „subroutine“, was „Unterprogramm“ bedeutet.)

Allerdings werden, auch von Programmierern, sowohl Funktionen als auch Prozeduren als „Funktion“ bezeichnet, vor allem da auch andere Programmiersprachen da keinen Unterschied machen. Deshalb wird auch in diesem Buch der Begriff „Funktion“ auch für Prozeduren verwendet.

Ist eine Funktion erst einmal eine Function, muss auch ein Rückgabetyp benannt werden. Der Rückgabetyp ist der Datentyp, den der Rückgabewert haben muss. Durch die Festlegung eines Rückgabetyps wird sichergestellt, dass die aufrufende Funktion mit dem Rückgabewert fehlerfrei operieren kann. Um einen Rückgabetyp festzulegen, hängen Sie an die Funktionsdeklaration einfach As und den Datentyp an. Ein Beispiel: Im Folgenden sehen Sie eine Prozedur mit zwei Parametern, darunter eine Funktion mit den gleichen Parametern, aber (da es eine Funktion ist) außerdem einem Rückgabetyp.

Code:  

Private Sub MeineProzedur(ByRef Daten As Integer(), ByVal Operation As String)
Private Function MeineFunktion(ByRef Daten As Integer(), ByVal Operation As String) As Boolean

Sehr häufig bei selbstgeschriebenen Funktionen sind (wie im obigen Beispiel) Boolean-Rückgabetypen. Dabei gibt der Rückgabewert an, ob die Operationen, die die Funktion durchführt, erfolgreich verlaufen sind. (Das ist nicht immer so klar, wie es jetzt scheint, vor allem wenn Sie mit so instabilen Objekten wie Dateien oder Netzwerkverbindungen arbeiten.) Ist alles glatt gelaufen, wird True zurückgegeben, sonst False.

Rückgabe Bearbeiten

Damit wären wir auch gleich beim nächsten Problem. Wie kann man nun einen Wert zurückgeben? Zum Glück geht das ganz einfach mit der Return-Anweisung. Jetzt ist der Zeitpunkt für ein praktisches Beispiel gekommen. Eine Funktion soll einen Wert verdoppeln und das Ergebnis zurückgeben. Der folgende Code löst dieses Problem.

  Code:  

Public Class Form1

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Dim a As Integer = 2
        Dim b As Integer = Verdoppeln(a)
        MessageBox.Show(b)
    End Sub

    Private Function Verdoppeln(ByVal Zahl As Integer) As Integer
        Dim Doppel As Integer = 2 * Zahl
        Return Doppel
    End Function
End Class

  Ausgabe:  

4

Die Funktion Verdoppeln wird von Form1_Load aus aufgerufen, für den Parameter Zahl wird der Wert von a, 2, übergeben. In der Funktion wird zunächst die Verdopplung durchgeführt und das Ergebnis, in diesem Falle 4, in der Variablen Doppel zwischengespeichert. Dann kommt das eigentlich Interessante, die Return-Anweisung. Die besteht, wie man leicht sieht, aus dem Schlüsselwort Return und dem Rückgabewert, hier der Wert von Doppel, also in diesem Falle 4.

Jeder mögliche Ausdruck kann mit Return zurückgegeben werden, also etwa ein Literal, ein Variablenwert (wie oben) oder auch das Ergebnis einer oder mehrerer Operationen. Daher kann man die Funktion Verdoppeln auch kürzer schreiben, indem man das Ergebnis der Multiplikationsoperation direkt zurückgibt.

  Code:  

Private Function Verdoppeln(ByVal Zahl As Integer) As Integer
    Return 2 * Zahl
End Function

Rückgabewerte können wie Variablenwerte oder Literale verwendet werden, z.B. kann der Rückgabewert von Verdoppeln direkt als Parameter an die MessageBox.Show-Funktion verwendet werden, sodass sich die Funktion Form1_Load wie folgt verkürzt:

  Code:  

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    MessageBox.Show(Verdoppeln(2))
End Sub

  Ausgabe:  

4

Manchmal ist es vonnöten, an die aufrufende Funktion mehrere Werte zurückzugeben. Eine entsprechende Möglichkeit über mehrere Rückgabewerte ist in Visual Basic .NET wie auch in anderen Programmiersprachen nicht vorgesehen, man kann sie jedoch über ByRef-Parameter in einer Prozedur nachbauen, z.B.:

  Code:  

Private Sub ZweiRückgabewerte(ByVal Wert1 As Integer, ByVal Wert2 As Integer, ByVal Daten As String, ByRef Ergebnis1 As Boolean, ByRef Ergebnis2 As Integer)

Hier werden drei Datenparameter übergeben, die die für die Funktion erforderlichen Daten enthalten. Sie heißen Wert1, Wert2 und Daten. Die Rückgabeparameter Ergebnis1 und Ergebnis2 geben die Ergebnisse an die aufrufende Funktion zurück. Die Rückgabewerte werden auf den Variablen durch einfache Zuweisungsoperationen gespeichert.

Noch ein Tipp: Man muss den Rückgabewert von Funktionen nicht innerhalb der aufrufenden Funktion verwerten. Man kann eine Funktion auch wie eine Prozedur aufrufen. Zum Beispiel hätte in der Form1_Load-Funktion oben auch folgender Befehl stehen können:

  Code:  

Verdoppeln(5)

Der Rückgabewert verschwindet dabei auf Nimmerwiedersehen. In diesem Fall ist das natürlich sinnlos, denn die einzige Aufgabe der Funktion ist die Berechnung des Rückgabewertes. Allerdings gibt es auch Funktionen, in denen der Rückgabewert nicht immer von Belang ist. Ein Beispiel ist die MessageBox.Show-Funktion, deren Funktionsdeklaration wie folgt aussieht:

  Code:  

Public Shared Function Show (text As String) As DialogResult

Wundern Sie sich nicht über die zwei Schlüsselwörter am Anfang. Public ist eine andere Option neben Private. Diese Optionen regeln die Sichtbarkeit von Funktionen aus anderen Objekten heraus. Bis jetzt verwenden wir nur ein Objekt, nämlich Form1. Daher ist für uns die Funktionssichtbarkeit unerheblich, wir verwenden aus Einfachheitsgründen immer Private. Das Shared regelt die Zugehörigkeit innerhalb des Objektes. Auf diesen und den Aspekt der Funktionssichtbarkeit gehen wir später genauer ein.

Interessant ist jetzt nur die Tatsache, dass die MessageBox.Show-Funktion einen Rückgabewert hat, nämlich ein System.Windows.Forms.DialogResult-Objekt. (Hier nur als DialogResult, da sich das MessageBox-Objekt im selben Namensraum befindet.) DialogResult fällt bei der Hauptaufgabe der MessageBox.Show-Funktion, der Darstellung eines Hinweisfeldes, als Nebenprodukt ab. Es enthält Informationen, welcher Knopf auf dem Hinweisfeld gedrückt wurde. Es gibt nämlich neben dem Standardfeld mit dem einzelnen Knopf OK, dessen Einsamkeit weitere Ergebnisprüfungen obsolet macht, noch andere, Ihnen aus der Arbeit mit Windows wahrscheinlich wohlbekannte Varianten wie Ja/Nein, Ja/Nein/Abbrechen oder Abbrechen/Wiederholen/Ignorieren. In Kürze werden wir auf diese Varianten genauer eingehen.

Frühzeitiges Verlassen Bearbeiten

Manchmal möchte man nicht, dass alle Befehle in einer Funktion ausgeführt werden. Dann kann man die Funktion vorzeitig verlassen. Dafür gibt es zum Glück nicht noch eine extra Anweisung. Das übernimmt ebenfalls die Return-Anweisung. Ein Aufruf der Return-Anweisung sorgt dafür, dass die Funktion sofort verlassen wird. Bis jetzt ist uns das noch nicht aufgefallen, weil die Return-Anweisung immer der letzte Befehl in unseren Funktionen war.

Funktionen erfordern, dass jeder Aufruf irgendwann in einer Return-Anweisung endet. Schließlich brauchen wir ja einen Rückgabewert. Bei Prozeduren ist eine Return-Anweisung eigentlich nicht nötig (wie die Form1_Load-Prozedur beweist), allerdings ist auch hier die Benutzung der Return-Anweisung möglich. Dann steht das Return aber alleine, einen Rückgabewert hat eine Prozedur schließlich nicht. (Analogie: Return-Anweisungen in einer Funktion müssen einen Rückgabewert haben.)

Ein kleines Beispiel soll die Auswirkungen der Return-Anweisung verdeutlichen.

  Code:  

Public Class Form1

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Testprozedur()
    End Sub

    Private Sub Testprozedur()
        MessageBox.Show("Hallo")
        Return
        MessageBox.Show("Welt!")
    End Sub
End Class

  Ausgabe:  

Hallo

Hier wird die Testprozedur aufgerufen. Nach der Ausgabe "Hallo" wird die Return-Anweisung aufgerufen und damit die Prozedur verlassen. Deshalb wird der zweite Aufruf der MessageBox.Show-Funktion nicht mehr ausgeführt.

Drei Anmerkungen noch: Erstens können natürlich innerhalb einer Funktion beliebig viele Return-Anweisungen stehen, vor allem bei verzweigten Bedingungsbäumen. Drittens gibt es noch eine zweite Möglichkeit, Funktionen zu verlassen und Rückgabewerte zu speichern. Statt Return schreibt man Exit Function bzw. Exit Sub. Den Rückgabewert muss man vorher einer Pseudovariable zuweisen, die genauso heißt wie die Funktion. (Also zum Beispiel MeineFunktion = 5.)