Visual Basic .NET: Felder

Aus Wikibooks
Wechseln zu: Navigation, Suche

Oft ist es von Vorteil, bestimmte Variablen thematisch zu gruppieren, um sie einfacher verarbeiten zu können. Zum Beispiel nehmen Simulationen Messreihen auf oder Mediaplayer stellen einen Film als viele Bildpunkte dar. In beiden Fällen erscheint es schwachsinnig, für jeden Wert eine einzelne Variable anzulegen. Das Mittel der Wahl sind hier Felder. Felder (nach dem englischen Begriff auch Arrays genannt) sind spezielle Variablen, die mehrere Werte eines bestimmten Datentypes aufnehmen können. Die Implementation ist in Visual Basic .NET gut gelungen, offenbart jedoch auch eine Schwachstelle.

Eindimensionale Felder[Bearbeiten]

In einem Feld wird jeder Wert durch eine Zahl, den sogenannten Index, repräsentiert. Da jeder Index innerhalb eines Feldes nur einmal vergeben wird, bestimmt ein Paar aus Feldname und Index einen Wert eindeutig. Das heißt, wenn Sie immer den gleichen Feldnamen und den gleichen Index angeben, werden Sie immer den gleichen Wert erhalten, genauso wie wenn Sie eine Variable über den immer gleichen Namen ansprechen.

Die Indizes der Feldwerte werden automatisch vergeben, es handelt sich hier immer um einen zusammenhängenden Bereich von Ganzzahlen. Dieser Bereich beginnt immer bei 0, man sagt auch, das Feld ist nullbasiert. Die Obergrenze (auch Feldgrenze genannt) bestimmt der Programmierer bei der Deklaration selbst.

Die Deklaration eines Feldes ähnelt der einer normalen Variable, nur wird direkt hinter dem Feldnamen in Klammern die Feldgrenze notiert. Die Elemente des Feldes spricht man auf die gleiche Weise an: Hinter dem Feldnamen wird in Klammern der Index des gewünschten Wertes notiert. Bei diesem Wert kann es sich auch um einen Operatorenausdruck handeln.

Crystal Clear app terminal.png Code:  

Dim Feld(3) As Integer
Feld(0) = 0
Feld(1) = 1
Feld(2) = Feld(0) + Feld(1)
Feld(3) = Feld(1) + Feld(2)
Console.WriteLine(Feld(0))
Console.WriteLine(Feld(1))
Console.WriteLine(Feld(2))
Console.WriteLine(Feld(3))

Crystal Clear app kscreensaver.png Ausgabe:  

(hier der Übersicht halber alles in einer Zeile)
0 1 1 2

Ganz besondere Schlaumeier haben es sofort erkannt: Dieses Beispiel berechnet die ersten 4 Glieder der  Fibonacci-Folge. Das ist aber gar nicht so wichtig, das Programm schon. In der ersten Zeile wird das Feld deklariert. Es enthält 4 (nicht 3!) Elemente mit den Indizes 0, 1, 2 und 3. Diese Feldelemente werden im folgenden initialisiert. Den ersten zwei Elementen mit den Indizes 0 und 1 werden die Werte 0 und 1 zugewiesen, die letzten zwei Elemente mit den Indizes 2 und 3 werden mit der Summe der jeweils vorhergehenden Werte initialisiert.

Es gibt noch eine zweite, für kleine Felder mit bekannten Werten meist komfortablere Form der Initialisierung:

Crystal Clear app terminal.png Code:  

Dim Feld() As Integer = {0, 1, 1, 2}
Console.WriteLine(Feld(0))
Console.WriteLine(Feld(1))
Console.WriteLine(Feld(2))
Console.WriteLine(Feld(3))

Crystal Clear app kscreensaver.png Ausgabe:  

(hier der Übersicht halber alles in einer Zeile)
0 1 1 2

Das Feld erhält hier die gleichen Werte wie oben. In den geschweiften Klammern stehen die Werte, die im Feld gespeichert werden sollen. Der Wert ganz links (1) wird in dem Element mit dem Index 0 gespeichert, der Wert rechts davon (1) in dem Element mit dem Index 1, der Wert rechts davon (2) in dem Element mit dem Index 2, und so weiter. Beachten Sie, dass bei dieser Art der Belegung keine Feldgrenze angegeben werden darf. Sie ergibt sich aus der Zahl der bereitgestellten Werte. So verhindert Visual Basic .NET einen Widerspruch, also dass für ein angelegtes Feld zu wenige oder (schlimmer noch) zu viele Werte bereitstehen.

Schon während dieses einfachen Beispiels zeigt sich ein Problem bei der Arbeit mit Feldern: die untere Feldgrenze 0. Sie sorgt dafür, dass ein Feld mit der Obergrenze 3 vier Elemente enthält, was nicht nur vielen Einsteigern spanisch vorkommt, sondern vor allem vielen Umsteigern, die von früheren Visual-Basic-Versionen gewohnt sind, neben der oberen auch die untere Feldgrenze festlegen zu können. Viele Visual-Basic-Programmierer deklarieren ein Feld mit der Obergrenze 3 und verwenden dann nur die Elemente 1 bis 3, damit es wieder 3 Elemente sind. Das ist allerdings unvorteilhaft, da das Index-0-Element nicht verwendet wird, aber unnötigerweise Speicherplatz belegt. Stattdessen sollte man die Obergrenze um eins verkleinern und dann bei allen Indizes konsequent eins abziehen.

Mehrdimensionale Felder[Bearbeiten]

Stellen Sie sich ein Schachbrett vor. Sollten Sie die Zustände der 64 Felder speichern wollen, wäre ein Feld ideal. Wahrscheinlich würden Sie das entsprechende Feld so deklarieren:

Crystal Clear app terminal.png Code:  

Dim Schachbrett(63) As Integer

Zur Zustandsspeicherung verwende ich hier String-Variablen, ein leerer String ("") bedeutet also ein leeres Feld, ein String wie "wBauer" könnte einen weißen Bauer darstellen. Später lernen wir mit Enumerationen und Typen zwei objektorientierte Möglichkeiten kennen, die Speicherung solcher Daten effizienter zu gestalten.

Das Problem bei der Darstellung mit einem solchen Feld ist die ziemlich umständliche Nutzung. Wüssten Sie etwa auf Anhieb, wo das Feld 50 liegt oder wieweit es vom Feld 40 entfernt ist? Unten sehen Sie links die jetzige Darstellung des Schachfeldes mit einem Index pro Feldelement, rechts eine viel pragmatischere und sinnvollere Darstellung mithilfe von zwei Indizes pro Feldelement. Ein entsprechendes Feld heißt aufgrund der zwei Indizes zweidimensional. Entsprechend ist ein Feld, in dem jedes Element über einen Index angesprochen wird, eindimensional. Ein Feld mit mehr als einem Index heißt allgemein mehrdimensional.

0 1 2 3 4 5 6 7
8 9 10 11 12 13 14 15
16 17 18 19 20 21 22 23
24 25 26 27 28 29 30 31
32 33 34 35 36 37 38 39
40 41 42 43 44 45 46 47
48 49 50 51 52 53 54 55
56 57 58 59 60 61 62 63
0-0 0-1 0-2 0-3 0-4 0-5 0-6 0-7
1-0 1-1 1-2 1-3 1-4 1-5 1-6 1-7
2-0 2-1 2-2 2-3 2-4 2-5 2-6 2-7
3-0 3-1 3-2 3-3 3-4 3-5 3-6 3-7
4-0 4-1 4-2 4-3 4-4 4-5 4-6 4-7
5-0 5-1 5-2 5-3 5-4 5-5 5-6 5-7
6-0 6-1 6-2 6-3 6-4 6-5 6-6 6-7
7-0 7-1 7-2 7-3 7-4 7-5 7-6 7-7

Ein mehrdimensionales Feld wird deklariert, indem in der Klammer, in dem beim eindimensionalen Feld die Feldgrenze steht, die Feldgrenzen von Kommata getrennt geschrieben werden.

Dim Schachbrett(7,7) As String

Wollte man statt acht nur sechs Reihen im Schachbrett haben, müsste man statt (7,7) die Feldgrenzen mit (5,7) festlegen. Sollte jede der acht Reihen nur vier Felder enthalten, würden die Feldgrenzen (7,3) heißen. Der Zugriff auf die Elemente erfolgt analog zur Deklaration, wie das folgende Beispiel zeigt, in der nicht alle Feldelemente mit Werten belegt werden (das würde den Rahmen sprengen).

Crystal Clear app terminal.png Code:  

Dim Schachbrett(7,7) As String
Schachbrett(0,0) = "" 'linkes oberes Feld leer
Schachbrett(1,0) = "wBauer" 'auf dem Feld darunter ein weißer Bauer
If Schachbrett(0,0) = "" Then 'wenn das linke obere Feld leer ist...
    Schachbrett(0,7) = Schachbrett(0,0) '... ist das rechte obere Feld auch leer
End If

Die einseitige Entscheidung am Ende ist ziemlich unsinnig, zeigt aber, dass Feldelemente überall verwendet werden dürfen, wo auch normale Variablen verwendet werden dürfen.

Wie für eindimensionale Felder gibt es auch für mehrdimensionale Felder die Möglichkeit, sie bei der Deklaration gleich zu initialisieren. Im folgenden Beispiel erstelle ich dazu ein Feld mit 3x2 Elementen, also den Obergrenzen 2 und 1.

Crystal Clear app terminal.png Code:  

Dim MeinFeld(,) As Integer = {{1,2},{3,4},{5,6}}

Die Anzahl der Kommas in den runden Klammern bestimmt die Anzahl von Dimensionen. Es müssen soviel Kommas sein, wie auch bei der Deklaration des Feldes ohne Initialisierung verwendet werden würden. Die Anzahl der Kommas ist also um eins geringer als die Anzahl der Felddimensionen. Das zweidimensionale Feld wird in dieser Initialisierung als eindimensionales Feld von eindimensionalen Feldern angesehen. Jede untergeordnete geschweifte Klammer definiert eine Gruppe von Elementen, die den ersten Index gemeinsam haben. Die Elemente, in denen die Werte 1 und 2 gespeichert sind, haben beide 0 als ersten Index. Innerhalb der Klammer wird der zweite Index hochgezählt. So hat das Element mit dem Wert 2 als ersten Index 0 und als zweiten Index 1, d.h. MeinFeld(0,1) = 2. (Das Gleichheitszeichen ist hier als Gleichheitsoperator zu verstehen.) Die obige Initialisierung des Feldes MeinFeld ist äquivalent zu der folgenden „manuellen“ Belegung der Feldelemente.

Crystal Clear app terminal.png Code:  

Dim MeinFeld(2,1) As Integer
MeinFeld(0,0) = 1
MeinFeld(0,1) = 2
MeinFeld(1,0) = 3
MeinFeld(1,1) = 4
MeinFeld(2,0) = 5
MeinFeld(2,1) = 6

Redimensionierungen[Bearbeiten]

Oftmals ist es vonnöten, Feldgrenzen zu ändern, etwa wenn in ein Feld von Messwerten ein neuer Messwert eingetragen werden sollen, oder wenn ein Browser eine aufgerufene Adresse in seinem Verlauf speichern will. In Visual Basic .NET gibt es für solche Redimensionierungen (Neufestlegungen der Feldgrenzen) die ReDim-Anweisung.

Crystal Clear app terminal.png Code:  

Dim Feld(2) As Integer
Feld(0) = 1
Feld(1) = 2
Feld(2) = 3
ReDim Feld(3)
Feld(3) = 4
Console.WriteLine(Feld(0))

Crystal Clear app kscreensaver.png Ausgabe:  

0

In diesem Beispiel wird zunächst ein Feld mit der Feldgrenze 2, also mit 3 Elementen deklariert, die danach belegt werden. Danach wird das Feld mit ReDim vergrößert. Da der Datentyp nicht geändert werden kann, muss er auch nicht angegeben werden. Ansonsten ähnelt die Syntax der der Deklaration des Feldes, ausgenommen das ReDim-Schlüsselwort. Außerdem lässt die ReDim-Anweisung keine Initialisierung zu. Im Beispiel wird die Feldgrenze auf 3 festgelegt, also das Feld um 1 auf 4 Elemente vergrößert. In der folgenden Zeile wird das neu geschaffene Element belegt.

Allgemein gelten für Redimensionierungen aus meist offensichtlichen Gründen die folgenden Regeln:

  • Die Dimensionszahl darf sich nicht ändern. Ein eindimensionales Feld kann nicht plötzlich zweidimensional werden, da dadurch Aufrufe von Feldelementen mit nur einem Index fehlerhaft würden.
  • Der Datentyp kann aus dem selben Grund nicht geändert werden. Würde man ein Integer-Datenfeld als Byte-Datenfeld redimensionieren (wobei „redeklarieren“ ), würden Befehle wie Feld(0) = 300 fehlerhaft, da eine Bereichsüberschreitung vorliegt (kurz: der Wert passt nicht in das Feldelement).

In der letzten Zeile wird der Wert eines Feldelementes abgerufen. Wenn Sie das Beispiel ausführen, wird nicht, wie erwartet, 1 ausgegeben, sondern 0. Woran liegt das? Um diese Frage zu klären, werfen wir einen kleinen Blick in den Speicher. Wenn eine Variable deklariert wird, fordert das Programm beim Betriebssystem (in unserem Fall ja meist Windows) Speicher für die Variable an. Windows sucht im Arbeitsspeicher ein passendes, freies Stück heraus, reserviert es und meldet dem Programm die Adresse des reservierten Speichers, auf dem das Programm die Variable anlegen darf. (In Wahrheit ist das noch viel komplizierter, aber das ist gerade nicht so wichtig.) Wichtig ist, dass der Speicherplatz für die Variable nur so groß ist, dass die Variable gerade hineinpasst. Wenn wir nun unser Feld (welches im Prinzip nur eine etwas größere Variable mit mehreren Werten ist) redimensionieren, kann (und wird) der Fall eintreten, dass der Speicherplatz für das Feld nicht mehr ausreicht. Um Fehler zu vermeiden, fordert das Programm völlig neuen Speicher in der passenden Größe an und erstellt dort das Feld neu. Dabei werden die zuvor im Feld gespeicherten Werte aber nicht übernommen, alle Feldelemente werden nur mit den Standardwerten initialisiert. Deshalb sehen wir beim Abrufen eines Feldelementes nicht den vor der Redimensionierung gespeicherten Wert, sondern den Standardwert 0.

Die ReDim-Anweisung besitzt zum Glück eine Erweiterung, mit der sich dieses Problem beheben lässt. Dazu muss zwischen ReDim und den Feldnamen das Schlüsselwort Preserve notiert werden.

Crystal Clear app terminal.png Code:  

Dim Feld(2) As Integer
Feld(0) = 1
Feld(1) = 2
Feld(2) = 3
ReDim Preserve Feld(3)
Feld(3) = 4
Console.WriteLine(Feld(0))

Crystal Clear app kscreensaver.png Ausgabe:  

1

Wenn das Schlüsselwort Preserve angegeben ist, wird erst das neue Feld angelegt und alle Werte des alten Feldes in das neue Feld kopiert, bevor das alte Feld gelöscht wird. Alle Elemente des neuen Feldes, die durch die Vergrößerung entstanden und für die es deshalb im alten Feld noch keine Werte gab, werden mit dem Standardwert, hier 0, initialisiert. Im Beispiel wird also erst das neue Feld mit 4 Elementen erstellt, dann die 3 Elemente des alten Feldes in das neue Feld kopiert, und dann das alte Feld gelöscht. Damit immer alle Elemente des alten Feldes kopiert werden können und keines verloren geht, muss das neue Feld immer größer oder gleich groß sein (wobei letzteres praktisch nicht von Bedeutung ist, da dann die ganze Redimensionierung schwachsinnig wäre).

Leider hat die Redimensionierung einen extremen Nachteil: Wenn man ein Feld mehrere Male vergrößert, zum Beispiel weil man 100 Datensätze einliest und das Feld 100-mal um eins vergrößert, dann werden auch einhundertmal Werte kopiert. Stellen Sie sich mal vor, Sie müssten sich 100 Notizen machen und jedesmal alle alten Notizen erst wieder auf einen etwas größeren Zettel schreiben. Das dauert natürlich ewig, genauso beim andauernden Redimensionieren.

Sie haben jetzt zwei Optionen: Entweder, Sie kriegen vorher irgendwie raus, wie viel Platz Sie brauchen, um dann einen entsprechend großen Zettel zu nehmen bzw. ein ausreichend großes Feld zu deklarieren. Das Problem hier ist, dass sich die erforderliche Kapazität in echten Szenarien fast nie abschätzen lässt. Mit einem Riesenfeld, dessen Werte nach Bedarf belegt werden, sollte man auch nicht arbeiten, da man dann aufwendig zwischen belegten und nicht belegten Feldern unterscheiden müsste. Der zweite Ausweg wäre, an den vollen Zettel einen neuen unten anzukleben. Dieses Konzept ist in Visual Basic in der Objektorientierten Programmierung als sogenannte Collection (engl. Sammlung, auch „verkettete Liste“) verwirklicht. An so eine Liste können nach Bedarf neue Elemente hinzugefügt werden. Solche fortgeschrittenen objektorientierten Themen wollen wir in diesem Abschnitt aber noch nicht behandeln.

Feldfunktionen[Bearbeiten]

Wahrscheinlich ist Ihnen jetzt von dem ganzen Deklarieren, Initialisieren und Redimensionieren so schwindlig geworden, dass Ihnen vor lauter Aufregung die Feldgrenzen Ihrer Felder entfallen sind. Holen Sie sich erstmal ein Glas Wasser und eine Aspirin-Tablette, dann erkläre ich Ihnen, wie Sie Ihre Feldgrenzen programmgesteuert wiederfinden.

Dazu muss man wissen, dass in Visual Basic .NET alles ein Objekt ist. Bis jetzt kennen Sie vor allem das System.Windows.Forms.MessageBox-Objekt, von dem es nur eins gibt. (Das stimmt zwar so nicht, aber das soll später in der objektorientierten Programmierung Thema sein.) Jede Variable ist ein Objekt, vor allem sind auch Felder Objekte. Wie das MessageBox-Objekt mit seiner Show-Methode hat auch ein Feld Methoden. Die wahrscheinlich wichtigste ist GetUpperBound. Das Get kommt in vielen Methodennamen und steht dafür, dass diese Methode eine Eigenschaft des jeweiligen Objektes abruft, hier die obere Feldgrenze (engl. upper bound). (Analog zu Get ist Set, dass Methoden zum Einstellen einer Eigenschaft kennzeichnet. Zum Beispiel könnte ReDim auch SetUpperBound heißen.)

GetUpperBound ist eine Methode des Feldobjektes. Heißt das Feld z.B. MeinFeld, wird die Methode mit der bekannten Punktsyntax über die Syntax MeinFeld.GetUpperBound aufgerufen. So wie bei der Console.WriteLine-Methode in Klammern der anzuzeigende Text eingetragen werden muss, muss bei der GetUpperBound-Methode in Klammern eine Ganzzahl stehen. Diese Zahl gibt an, welche Feldgrenze zurückgegeben werden soll, da es ja bei mehrdimensionalen Feldern mehrere geben kann. Die erste Feldgrenze wird durch 0 repräsentiert. Wie man sieht, fängt wie bei Feldelementen auch hier die Zählung bei 0 an. Bei eindimensionalen Feldern müssen Sie also immer 0 angeben. Bei jeder darauffolgenden Feldgrenze erhöht sich die Zahl um 1. Ich möchte das mit einem Beispiel illustrieren.

Crystal Clear app terminal.png Code:  

Dim MeinFeld(5,9,3) As String, Feldgrenzen(2) As Integer
Feldgrenzen(0) = MeinFeld.GetUpperBound(0)
Feldgrenzen(1) = MeinFeld.GetUpperBound(1)
Feldgrenzen(2) = MeinFeld.GetUpperBound(2)
Console.WriteLine(Feldgrenzen(1))

Crystal Clear app kscreensaver.png Ausgabe:  

9

Da die GetUpperBound-Methode einen Wert ermittelt, hier die entsprechende Feldgrenze, kann man diesen Wert wie einen Literal einer Variable zuweisen. Auch die Ausgabe mit der Console.WriteLine-Methode ist denkbar. Viele Methoden ermitteln einen Wert, den Sie zurückgeben, deshalb heißen diese Werte Rückgabewerte. Im vorliegenden Beispiel geben die Aufrufe der MeinFeld.GetUpperBound-Methode die entsprechenden Feldgrenzen 5, 9 und 3 zurück, das Feld Feldgrenzen wird mit diesen Werten belegt. Das folgende Beispiel ist zum obigen äquivalent und zeigt noch einmal, dass Rückgabewerte überall verwendet werden können, wo auch literale Werte übergeben werden können.

Crystal Clear app terminal.png Code:  

Dim MeinFeld(5,9,3) As String
Dim Feldgrenzen() As Integer = {MeinFeld.GetUpperBound(0), MeinFeld.GetUpperBound(1), MeinFeld.GetUpperBound(2)}
Console.WriteLine(Feldgrenzen(1))

Crystal Clear app kscreensaver.png Ausgabe:  

9

Analog zu GetUpperBound funktioniert GetLowerBound, dass die untere Feldgrenze bestimmt. Da in unserem Fall die Indizes immer bei 0 beginnen, gibt diese Methode immer 0 zurück. Für unsere Zwecke ist die GetLowerBound-Methode uninteressant, in den allermeisten Fällen kommt man auch ohne eine andere Felduntergrenze aus.

Die Length-Eigenschaft eines Feldes gibt die Anzahl von Elementen zurück.

Crystal Clear app terminal.png Code:  

Dim MeinFeld(7,7) As Integer
Console.WriteLine(MeinFeld.Length)

Crystal Clear app kscreensaver.png Ausgabe:  

64 (8x8 Elemente)

Verwenden Sie MeinFeld.Length, wenn Sie die Anzahl der Elemente in der Feldvariable MeinFeld bestimmen wollen. Sie können diesen Ausdruck wie eine Variable verwenden, dürfen ihm aber keinen Wert zuweisen (eine weitere Eigenheit der OOP).

Eine Feldgrenze kann auch -1 sein. Wenn mindestens einer der Indizes eines Feldes -1 ist, bedeutet das, dass das Feld zwar leer ist, aber existiert. (In Fachtermini: Es ist Empty, aber nicht Nothing.) Jeder Versuch, auf ein solches leeres Feld zuzugreifen, schlägt fehl. Leere Felder können sehr nützlich sein, wenn die Anzahl der Elemente des Feldes bei der Deklaration nicht klar ist, etwa weil die Feldelemente in einer Datei gespeichert sind, sodass man das Feld erst nach und nach füllen kann. Dazu später mehr.

Eine weitere Feldfunktion ist die Sort-Methode, die, wie der Name schon sagt, das Feld sortiert. Der Bezeichner für diese Methode ist allerdings nicht MeinFeld.Sort, sondern Array.Sort (engl. array = Feld). Sort ist nämlich keine Methode des Feldes, sondern eine Methode des Array-Objektes, das dem MessageBox-Objekt ähnelt. In Klammern muss das Feld an die Methode übergeben werden, damit die Methode weiß, welches Feld zu sortieren ist. Außerdem ist zu beachten, dass Sort nur eindimensionale Felder sortieren kann.

Crystal Clear app terminal.png Code:  

Dim MeinFeld() As Integer = {1, 5, 8, 3, 8, 4, 7}
Array.Sort(MeinFeld)
Console.WriteLine(MeinFeld(0))
Console.WriteLine(MeinFeld(1))
Console.WriteLine(MeinFeld(2))
Console.WriteLine(MeinFeld(3))
Console.WriteLine(MeinFeld(4))
Console.WriteLine(MeinFeld(5))
Console.WriteLine(MeinFeld(6))

Dieses Beispiel erstellt ein Feld mit unsortierten Zahlenwerten, sortiert es dann und gibt die Werte in Reihenfolge aus. Wen es interessiert: Die Sort-Methode verwendet den  Quicksort-Algorithmus, der sich durch eine selbst im schlimmsten Fall noch durchschnittlich schnelle Ausführung auszeichnet.

Eine andere zum Sortieren nützliche Methode ist die Reverse-Methode, die das komplette Feld umdreht. Im folgenden Beispiel wird der Aufruf der Array.Sort-Methode durch einen Aufruf der Array.Reverse-Methode ergänzt. Für die Array.Reverse-Methode gilt dieselbe Einschränkung wie für Array.Sort: Es können nur eindimensionale Felder umgekehrt werden.

Crystal Clear app terminal.png Code:  

Dim MeinFeld() As Integer = {1, 5, 8, 3, 8, 4, 7}
Array.Sort(MeinFeld)
Array.Reverse(MeinFeld)
Console.WriteLine(MeinFeld(0))
Console.WriteLine(MeinFeld(1))
Console.WriteLine(MeinFeld(2))
Console.WriteLine(MeinFeld(3))
Console.WriteLine(MeinFeld(4))
Console.WriteLine(MeinFeld(5))
Console.WriteLine(MeinFeld(6))

Crystal Clear app kscreensaver.png Ausgabe:  

(hier der Übersicht halber alles in einer Zeile)
8 8 7 5 4 3 1

Kaskadierte Felder[Bearbeiten]

Es gibt noch eine zweite Möglichkeit, mehrdimensionale Felder zu realisieren, nämlich als kaskadiertes (verschachteltes) Feld im Feld. Werfen Sie einen Blick auf die folgenden Deklarationen:

Crystal Clear app terminal.png Code:  

Dim Feld1(5,6) As Integer
Dim Feld2(5)() As Integer
ReDim Feld2(0)(2)
ReDim Feld2(1)(6)
ReDim Feld2(2)(5)
ReDim Feld2(3)(1)
ReDim Feld2(4)(4)
ReDim Feld2(5)(3)
Dim Feld3()() As Integer = {New Integer() {1, 2}, New Integer() {3, 4, 5} }

In der ersten Zeile entsteht ein normales mehrdimensionales Feld mit 42 Elementen (nicht 30!). In der zweiten Zeile wird ein eindimensionales Feld deklariert, dessen 6 Werte nicht einfache Variablen, sondern jeweils wieder Felder sind. Auch wenn wir in diesem Beispiel keine Initialisierung vornehmen, müssen die zweiten Feldgrenzen offen bleiben. In den nächsten 6 Zeilen werden nämlich die 6 Einzelfelder durch Redimensionierung erstellt. Beachten Sie hierbei vor allem, dass die Feldgrenzen der einzelnen Felder voneinander unabhängig sind, während die 2. Dimension eines normalen 2-dimensionalen Feldes einheitlich sein muss. Damit eignen sich kaskadierte Felder vor allem für dynamische Inhalte, in denen die Zahl von Elementen in einem Teilfeld variiert und sich mit der Zeit verändert. Man kann auch noch mehr Dimensionen zu einer Feldkaskade hinzufügen, allerdings leidet dann die Übersicht.

In der letzten Zeile haben wir noch ein Beispiel für die Initialisierung von kaskadierten Feldern. Hierbei kann das Teilfeld nicht so komfortabel wie bei einem mehrdimensionalen Feld initialisiert werden. Stattdessen müssen wir das Feld im Speicher erstellen und dann als Wert im Feld speichern. Das hört sich jetzt sehr komplex an (und wenn man sich die Vorgänge im Speicher anschaut, ist es das auch, aber das ist ja nicht unser Thema). Deshalb nur so viel: Mit der New-Anweisung wird ein Feld im Speicher erstellt und sofort initialisiert. (Das Deklarieren nur mit Feldgrenze ist hier nicht möglich.) Dabei folgt auf das New-Schlüsselwort der Datentyp der Feldelemente und dann der uns mittlerweile gut bekannte Klammerwust zum Festlegen der Feldstruktur. Dann kommen in geschweiften Klammern die Werte. Alles wie gehabt also, nur dass die Klammern nach und nicht vor dem Datentyp stehen und dass kein Feldname vergeben wird.

Wie man leicht sieht, eignen sich kaskadierte Felder nicht für Felder mit vielen Werten, die von Hand eingetippt werden. Dafür ist ein konventionelles mehrdimensionales Feld besser geeignet. Die Stärken von kaskadierten Feldern liegen in dynamischen Inhalten oder solchen, die vom Computer nach einer einzelnen Formel berechnet werden können. Wie das geht, sehen Sie im nächsten Kapitel.