Schleifen in VB.Net
Autor/Einsender:   Thomas Becker
Anregungen/Tipps an: Thomas Becker
Wir alle haben in unseren Programmen Schleifen integriert. Oft verlangt die Programmierung eine Überlegung, welche Schleifenform wann die Günstigste ist. Dabei können Schleifen mit durchdachter Bedingungsformulierung ebenso Objektmember liefern, Schritte überspringen oder gar rückwärts laufen. Aus diesen Grunde macht eine etwas tiefere Betrachtung Sinn, um alle Möglichkeiten voll ausschöpfen zu können.
For/Next -Schleife
For/Each - Schleife
Do/ Loop - Schleife
While - Schleife
Kompakt: Verschachtelte Schleifen
Hinweise zum Einsatz in der Praxis
Zu jedem Schleifentyp sind die besonderen Einsatzgebiete angeführt und werden anhand praktischer Beispiele erläutert.
For/Next -Schleife
Die For/Next-Schleife ist eine beliebte Zählschleife. Sie ist sinnvoll einsetzbar wenn die Anzahl der Durchläufe bekannt ist. Außerdem erhält man einen Index. Eine Zahl, die sich mit jedem Durchlauf erhöht. Zudem kann man optional mittels Step angeben, um wie viel Schritte sich der Index erhöht. Des weiteren kann die Variablendeklaration gleich im Schleifenkopf erfolgen. Es steht dem Entwickler frei, die Variable hinter Next zu schreiben. Dies kann bei verschachtelten Schleifen nützlich sein.
Beispiel 1, Das Grundprinzip einer For-Schleife:
 
For i As Integer = 0 To 19 ' 20 Durchläufe

   If ... Then Continue For
   If ... Then Exit For

Next i
 
Alle Schleifenarten erlauben auch die Sprunganweisungen Continue und Exit. Continue setzt die Schleife sofort ab nächsten Durchgang fort, Exit bricht die aktuelle Schleife ab.
Im Gegensatz zu GoTo-Sprungmarken gilt die Verwendung der Sprunganweisungen Continue und Exit nicht als schlechter Stil, da diese in komplizierten Schleifen unvermeidbar sind.
Der Index sollte aus Performancegründen möglichst immer Integer sein. Prinzipiell ist aber auch ein anderer numerische Variablentyp zulässig. So ist Long und Decimal keine Hürde. Sehr vorsichtig sollte man mit reinen Gleitkomma-Werten (Single, Double) sein. Im folgenden Beispiel unterschlägt uns die Schleife deswegen einen ganzen Durchgang.
Beispiel 2, Gleitkommafehler der CPU:
 
For i As Single = 0 To 1 Step 0.05
  MsgBox(i.ToString) 'Letzter Index nicht 1 sondern 0,9500002!
Next
 
Visual Basic verhält sich innerhalb der Schleife durchaus korrekt. 0,95 ist wegen dem CPU-Gleitkommafehler nun einmal nicht eins und ein weiterer Step (Schritt) wäre > 1.
Damit sind wir auch schon bei Step gelandet. Wie sinnvoll das Auslassen von Schleifen-Schritten sein kann, soll der nächste Code verdeutlichen. Wir durchlaufen hier die Schleife in 2er Schritten. Dadurch können wir Felder aus einem Array in 2 verschiedene ListBoxen trennen.
Beispiel 3, Schleife befüllt in 2er-Schritten verschiedene ListBoxen aus einer Quelle:
 
Public Class Form1

  Private Sub Form1_Load(ByVal sender As System.Object, ByVal e _
          As System.EventArgs) Handles MyBase.Load
    Dim MyArray() As String = New String() {"Heidelbeeren", _
        "Cherimoya", "Gurken", "Curuba", "Pflaumen", "Durian", _
        "Kirschen", "Datteln", "Himbeere", "Guave", "Birnen", _
        "Mango", "Erdbeeren", "Papaya"}

    For i As Integer = 0 To MyArray.GetUpperBound(0) Step 2
      ListBox1.Items.Add(MyArray(i))
      ListBox2.Items.Add(MyArray(i + 1))
    Next
  End Sub

End Class
 
Im obigen Beispiel wird ein Stringarray, dass abwechselnd mit den Namen heimischer sowie exotischen Früchte gefüllt ist, in einer Schleife durchlaufen. Aufgrund der zweier Schritte (Step 2) der Schleife können nun immer 2 Datenfeld-Elemente (ArrayItems) an unterschiedliche Ziele übergeben werden. Dadurch werden die Sorten getrennt: Hiesige Früchte zur ListBox1, die Exoten zur ListBox2.
For/Next-Schleifen können auch rückwärts laufen, also vom größten Index beginnend. Dazu sind lediglich die Werte am Schleifenkopf umzudrehen sowie Step auf eine negative Zahl zu setzen.
Beispiel 4, Schleife läuft rückwärts durch Argb-Farben:
 
For i As Integer = 250 To 155 Step -1
  Button1.BackColor = Color.FromArgb(i, i, i)
  Threading.Thread.Sleep(10)
  Button1.Refresh()
Next
 
Kombiniert mit einer ähnlichen Vorwärtsschleife bekommt der Button übrigens einen interessanten Effekt.
For Each - Schleife
Jedes Array sowie jede Collection lässt sich damit durchlaufen. Die Schleife wandert von einem Item zum anderen. Die Variable (nach "For Each") muss dem Typ des Items des zu durchlaufenen Arrays entsprechen. Ist es beispielsweise ein Integerarray, wird die Variable als Integer deklariert, da jedes Item ein Integerobjekt ist. Die Besonderheit ist, das wir beim Durchlauf jeweils ein Datenobjekt mit all seinen Methoden und Eigenschaften zur Verfügung haben.
Beispiel 5, Das Grundprinzip einer For Each-Schleife:
 
For Each printer As String In _
    Printing.PrinterSettings.InstalledPrinters
  If ... Then Continue For
  If ... Then Exit For
Next
 
Beispiel 6, Durchlaufen eines Fileinfo-Objektes und Hinzufügen von Daten in eine ListBox:
 
Dim diPfad As New IO.DirectoryInfo("c:\windows")

For Each file As IO.FileInfo In diPfad.GetFiles()
  ListBox1.Items.Add(file.Name.ToString & "  " & _
       file.LastWriteTime.ToShortDateString)
Next
 
Im obigen Beispiel wird ein GetFiles-Array durchlaufen. Das jeweils von der Variable file bereitgestellte FileInfo-Objekt wird genutzt, um deren Eigenschaften Name und LastWriteTime auszulesen.
Do/Loop - Schleife
Als mit Abstand umfangreichstes Schleifenkonstrukt kann diese Schleifenform angesehen werden und lässt präzise Bedingungsformulierung zu.
Beispiel 7, Das Grundprinzip einer Do/Loop-Schleife:
 
Do
  If ... Then Continue Do
  If ... Then Exit Do
Loop
 
Die Schleifenbedingung:
  • Until (Ausführung bis [Anweisung]) oder
  • While (Ausführung während [Anweisung])
  • kann am Kopf oder Fuß der Schleife stehen
  • Schleife ohne Bedingung ist ebenso zulässig

Beispiel 8, Die Do/Loop-Schleifenformen im Überblick:

 
=== Kopfbedingung Until ===

 ' Ende wenn Until-Bedingung den Schleifenkopf erreicht
Do Until ComboBox1.Items.Count > 90

=== Fußbedingung Until ===

 ' Ende wenn Until-Bedingung das Schleifenende erreicht
Loop Until ComboBox1.Items.Count > 90

=== Kopfbedingung While ===

 ' Läuft solange While-Bedingung am Schleifenkopf vorliegt
Do While ComboBox1.Items.Count > 90

=== Fußbedingung While ===

 ' Läuft solange While-Bedingung am Schleifenende vorliegt
Loop While ComboBox1.Items.Count > 90
 
Als Bedingung ist auch in einer Do/ Loop-Schleife alles erlaubt, was auch in If-Konstrukten formulierbar ist.
While - Schleife
Die While-Schleife ist ein Konstrukt, indem eine Bedingung am Schleifenkopf festgelegt wird. Diese läuft dann solange während (engl. while) die Bedingung erfüllt ist. Im Gegensatz zu VB6 endet eine While-Schleife nicht mit Wend, sondern mit End While. Dies dient einer einheitlicheren Syntax. Wer dennoch Wend eingibt, dem wird die IDE von Visual Studio dies automatisch in die neue Schreibweise ändern.
Beispiel 9, Das Grundprinzip einer While-Schleife:
 
While ComboBox1.Items.Count < 90
  If ... Then Continue While
  If ... Then Exit While
End While
 
Als Bedingung kann praktisch alles verwendet werden was in If-Konstrukten erlaubt ist.
Kompakt: Verschachtelte Schleifen
Grundsätzlich können Schleifen beliebig oft ineinander verschachtelt werden. Allerdings sollte man bedenken, dass mit jeder zusätzlich verschachtelten Schleife die Gefahr von Fehlern steigt, und diese im Schleifencode natürlich auch entsprechend schwerer zu lokalisieren sind.
Beispiel 10, Grundprinzip Verschachtelung:
 
Dim i As Integer, k As Integer

 'äußere Schleife
For k = 1 To 5
   'erste innere Schleife
  For i = 1 To 20

  Next i

   'zweite innere Schleife
  For i = 1 To 20

  Next i

Next k

 'abschließende separate Schleife
For i = 1 To 20

Next i
 
Anhand der automatischen Code-Einrückungen der Visual Studio-IDE kann geprüft werden, ob die verschiedenen Schleifen richtig erkannt werden bzw. ob ein logischer Fehler vorliegen könnte. Man unterscheidet verschachtelte Schleifen in zwei Arten. Es gibt unabhängige und abhängige Verschachtelungen. Im nächsten Beispiel wird die Verschachtelungsart gezeigt, welche keine Auswirkung auf die innere Schleifenbedingung hat.
Beispiel 11, Verschachtelte unabhängige Schleife schreibt und liest ein 2-dimensionales Array:
 
Dim rows As Integer = 4
Dim cols As Integer = 4
Dim arr(rows - 1, cols - 1) As Integer
Dim row, col, i As Integer

For row = 0 To rows - 1
  For col = 0 To cols - 1
    arr(row, col) = i
    i += 1
  Next col
Next row

 '2 dim. Array auslesen
For row = 0 To rows - 1
  For col = 0 To cols - 1
    MsgBox(arr(row, col))
  Next col
Next row
 
Verschachtelungen können aber auch so gestaltet werden, das eine innere Schleife als Bedingung den Wert der Äußeren erhält. In diesem Falle spricht man von der abhängigen Verschachtelungsart.
Beispiel 12, Verschachtelte abhängige Schleife durchläuft Buchstaben:
 
Dim i As Integer, j As Integer, Ergebnis As String = ""
Dim Alphabet As String = "ABCDEFGH"

 ' äußere Schleife
For i = 0 To 7
   ' innere Schleife
  For j = 0 To i '<- i ist auch hier im Einsatz!
    Ergebnis += Alphabet.Chars(i)
  Next j
  Ergebnis += vbNewLine
Next i

MessageBox.Show(Ergebnis)
 
Die Variable Ergebnis erhält im obigen Beispiel folgenden Inhalt:
A
BB
CCC
DDDD
EEEEE
FFFFFF
GGGGGGG
HHHHHHHH
Möglich wird diese Abhängigkeit, da innere Schleifen von der Parentschleife immer wieder aufgerufen werden. Somit darf ihre Schleifenbedingung variieren.
Hinweise zum Einsatz in der Praxis
Schleifen können bei längerer Durchlaufzeit zum Einfrieren der Form führen. In diesem Fall kann man mittels Application.DoEvents ein Neuzeichnen der Form erzwingen. Dies verlangsamt jedoch den Schleifendurchlauf.
Beispiel 13, Neuzeichnen der überlasteten Form mit DoEvents:
 
For i As Integer = 1 To 2000
  Label1.Text = i.ToString
  Application.DoEvents() 'ohne DoEvents stockt die Form!
Next
 
Wesentlich besser ist es, die Schleife nach Möglichkeit in einem eigenen Thread (Stichwort: Multithreading) auszuführen. Dadurch wird der Formthread entlastet und so kann jederzeit die Form verschoben werden und reagiert problemlos auf weitere Benutzereingaben. Somit kann diese Schleifenprozedur mittels Abbruch-Button beendet werden.
Beispiel 14, Schleife im Nebenthread "entsperrt" die überlastete Form und lässt so einen vorzeitigen Abbruch zu:
 
Imports System.Threading

Public Class Form1

Delegate Sub UpdateLabel(ByVal Wert As String)
Dim T As Thread, Counter As Integer

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e _
      As System.EventArgs) Handles MyBase.Load
  Button1.Text = "Starten"
  Button2.Text = "Abbruch"
End Sub

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e _
      As System.EventArgs) Handles Button1.Click
  Counter = 0
  T = New Thread(AddressOf ThreadZiel)
  T.Start()
End Sub

Private Sub Button2_Click(ByVal sender As System.Object, ByVal e _
      As System.EventArgs) Handles Button2.Click
   ' Threadabbruch!
  If T.ThreadState = ThreadState.WaitSleepJoin Or T.ThreadState = _
       ThreadState.Running Then
    T.Abort()
    MsgBox("Vorzeitiger Thread-Abbruch bei " & Counter.ToString)
  End If
End Sub

Private Sub ThreadZiel()
  For i As Integer = 0 To 2000
    Thread.Sleep(10)
    Label1.BeginInvoke(New UpdateLabel(AddressOf LabelBearbeit), _
           i.ToString)
    Counter = i
  Next

  MsgBox("Normales Thread-Ende mit " & Counter.ToString)
End Sub

Private Sub LabelBearbeit(ByVal Wert As String)
  Label1.Text = Wert
End Sub

End Class
 
Schleifen können schneller durchlaufen werden, indem man einen vorhandenen numerischen Index nicht oft verwendet. In langen Arrays und Collections verliert jeder wiederholte gleiche Indexaufruf wertvolle Rechenzeit, da das Item jedes Mal erneut in der Auflistung gesucht werden muss. Da sollte man lieber beherzt zu einer zusätzlichen Variablen greifen, welcher lokal der Inhalt des Items zugewiesen wird.
Beispiel 15, Schleife ruft zu häufig ein ArrayIndex auf:
 
For i As Integer = 0 To StrArray.Length - 1
  If StrArray(i).Contains("A") And StrArray(i) <> "" Then
    StrArray(i) = StrArray(i).Replace("ABC", "")
    StrArray(i) = StrArray(i).Insert(0, "123")
  End If
Next
 
Beispiel 16, zusätzliche Variable verhindert ständigen Indexabruf:
 
Dim Wert As String

For i As Integer = 0 To StrArray.Length - 1
  Wert = StrArray(i)
  If Wert.Contains("A") And Wert <> "" Then
    Wert = Wert.Replace("A", "")
    Wert = Wert.Insert(0, "123")
  End If
Next
 
In einer Schleife ist übrigens auch das Instanzieren einer Variable erlaubt. Diese Instanz gilt dann lokal für jeweils einen Schleifendurchgang und wird im neuen Durchgang automatisch erneuert.
Beispiel 17, eine in der Schleife instanzierte Variable behält ihren Wert nur im aktuellen Durchgang:
 
Dim n As Integer = 10

For i As Integer = 1 To 3
  Dim Labl As Label = New Label

   Labl.Name = "Label" & i
   Labl.Text = "Label" & i
   Labl.Top = 100
   Labl.Left = n
   n += Labl.Width
   Controls.Add(Labl)
Next
 
Um entsprechend einer Anforderung einen sauberen, übersichtlichen und schell ablaufenden Code zu schreiben, verlangt es bei der Programmentwicklung oft die Überlegung, wann welche Schleifenform am Besten eingesetzt werden soll. Dieses Tutorial zeigt auf und gibt einen Überblick, wie welche Schleifen verwendet werden können.
Natürlich erhebt es keinen Anspruch auf Vollständigkeit, und sollte es Ihrer Meinung nach an der ein oder anderen Stelle erweitert oder noch vertieft werden, geben Sie einfach dem Autor Bescheid.
Bei Fragen zu diesem Tutorial nutzen Sie bitte unser VB.Net-Forum.



Zum Seitenanfang

Startseite | VB-/VBA-Tipps | Projekte | Tutorials | API-Referenz | Komponenten | Bücherecke | Gewinnspiele | VB-/VBA-Forum | DirectX-Forum | VB.Net | .Net-Forum | Foren-Archiv | Chat | Spielplatz | Links | Suchen | Stichwortverzeichnis | Feedback | Impressum

Seite empfehlen Bug-Report
Letzte Aktualisierung: Dienstag, 27. Dezember 2011