1. Array vom Typ string
Ich will dir kurz was über Arrays vom Typ string erzählen.
Wie wir schon gesagt haben, kann ein Array jeden Typ haben. Das heißt, du kannst auch ein Array vom Typ string erstellen. So könnte der Code aussehen, wenn wir ein Programm schreiben müssten, das „10 Zeilen von der Tastatur einliest und sie in umgekehrter Reihenfolge ausgibt“.
string[] array = new string[10]; // Wir erstellen ein Array-Objekt mit 10 Elementen
for (int i = 0; i < 10; i++) // Schleife von 0 bis 9
{
array[i] = Console.ReadLine(); // Lies eine Zeile von der Tastatur und speichere sie im Array
}
for (int i = 9; i >= 0; i--) // Schleife von 9 bis 0
{
Console.WriteLine(array[i]); // Gib das aktuelle Array-Element aus
}
Der Code hat sich kaum verändert! Du musstest nur beim Erstellen des Arrays den Typ int durch string ersetzen. Sonst ist alles genau gleich!
2. Array vom Typ string im Speicher
Und noch ein nützlicher Fakt. Schau dir mal diese 3 Bilder an:
Bild 1. Wie ein string-Objekt im Speicher liegt:
Beachte, dass der Text der Zeichenkette nicht direkt in der Variable gespeichert wird: Dafür wird ein eigener Speicherblock reserviert. In der Variable vom Typ string wird die Adresse (Referenz) auf das Objekt mit dem Text gespeichert.
Bild 2. Wie ein Array von Ganzzahlen im Speicher liegt:
Dieses Bild hast du auch schon gesehen.
Bild 3. Wie ein Array von Zeichenketten im Speicher liegt:
Links siehst du die Array-Variable vom Typ string[] (speichert die Adresse des Array-Objekts).
In der Mitte — das Array-Objekt vom Typ string.
Und rechts — die string-Objekte, die irgendwelche Texte speichern.
In den Zellen des Array-Objekts vom Typ string werden nicht die Zeichenketten selbst (Texte) gespeichert, sondern deren Adressen (Referenzen). Genau wie in Variablen vom Typ string die Adressen der Zeichenketten (Texte) gespeichert werden.
3. Schnelle Initialisierung eines Arrays in C#
Arrays sind mega praktisch, deshalb haben die C#-Entwickler versucht, die Arbeit damit so bequem wie möglich zu machen. Das Erste, was sie gemacht haben, ist die Initialisierung von Arrays zu vereinfachen, also das Setzen von Startwerten.
Oft braucht ein Programm neben den Daten, die es irgendwoher liest, auch eigene interne Daten. Zum Beispiel müssen wir die Längen aller Monate in einem Array speichern. So könnte der Code aussehen:
int[] months = new int[12];
months[0] = 31; // Januar
months[1] = 28; // Februar
months[2] = 31; // März
months[3] = 30; // April
months[4] = 31; // Mai
months[5] = 30; // Juni
months[6] = 31; // Juli
months[7] = 31; // August
months[8] = 30; // September
months[9] = 31; // Oktober
months[10] = 30; // November
months[11] = 31; // Dezember
Aber es gibt einen kürzeren Weg — danke an die C#-Macher:
// Längen der Monate im Jahr
int[] months = new int[] { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
Du kannst einfach alle Werte des Arrays durch Kommas getrennt auflisten!
Ziemlich praktisch, oder? Aber das ist noch nicht alles.
Der Compiler kann sogar den Typ des Containers (Array-Objekt) anhand des Typs der Array-Variable bestimmen. Und um die Länge des Arrays zu bestimmen, zählt er einfach die Anzahl der Elemente in den geschweiften Klammern.
Deshalb kann man den Code noch kürzer schreiben:
// Längen der Monate im Jahr
int[] months = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
Ist das nicht schön? 🙂
Diese Schreibweise nennt man „schnelle Initialisierung eines Arrays“. Sie funktioniert übrigens nicht nur für int...
// Namen der Monate im Jahr
string[] months = { "Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember"};
4. Die foreach-Schleife
Das Durchlaufen aller Elemente eines Arrays ist so häufig, dass es dafür eine eigene Schleife gibt(!). Sie heißt foreach. Und sieht so aus:
foreach (int score in scores)
{
Console.WriteLine($"Punkte: {score}");
}
Hier läuft die Schleife die Elemente selbst durch ― kein manueller Index nötig. Du kannst die Elemente nicht direkt ändern (sie sind in der Schleife nur lesbar), aber es ist super praktisch, einfach mal „drüberzugehen“.
Der Compiler wandelt den foreach-Schleifen-Code in den folgenden Code um:
for (int i = 0; i < scores.Length; i++)
{
int score = scores[i];
Console.WriteLine($"Punkte: {score}");
}
Also keine Magie. Jetzt wird auch klar, warum du die Array-Elemente nicht über die Variable score ändern kannst.
Lass uns noch ein Beispiel schreiben: Wir berechnen die Summe aller Punkte.
int summe = 0;
foreach (int score in scores)
{
summe += score;
}
Console.WriteLine($"Summe aller Punkte: {summe}");
Wann welche Schleife verwenden?
- Wenn du einen Index brauchst oder Elemente ändern willst — for-Schleife.
- Wenn du einfach nur über die Werte gehen willst — foreach ist schneller und sauberer.
5. Indexierung vom Ende: Operator ^
Seit einiger Zeit kannst du in C# Elemente vom Ende des Arrays holen. Früher hast du, wenn du das letzte Element wolltest, sowas geschrieben:
int letzterPunkt = scores[scores.Length - 1];
Jetzt ist es viel einfacher. Du musst nur vor dem Index den Operator ^ schreiben, und es wird vom Ende gezählt:
int letzterPunkt = scores[^1]; // Letztes Element
int vorletzter = scores[^2]; // Vorletztes Element
- ^1 — das ist das erste vom Ende (also das letzte).
- ^2 — das zweite vom Ende.
Visualisierung
| Index | Wert im Array scores | Normaler Index | Index vom Ende |
|---|---|---|---|
| 0 | 10 | 0 | ^5 |
| 1 | 15 | 1 | ^4 |
| 2 | 8 | 2 | ^3 |
| 3 | 22 | 3 | ^2 |
| 4 | 17 | 4 | ^1 |
score[^1] = 17, score[^2] = 22 — easy und verständlich.
Wichtig! Beachte, dass die Indizes vom Ende mit 1 beginnen, nicht mit 0.
6. Bereiche: Operator .. (range)
Manchmal willst du einen Teil-Array aus dem Original-Array holen. In C# kannst du dafür den speziellen Bereichsoperator .. nutzen — das ist eine kurze und sehr praktische Art, ein „Stück“ Array zu bekommen.
So ein Teil-Array nennt man manchmal Slice (vom Englischen "slice"), und er wird durch zwei Grenzen definiert: Anfang und Ende.
Wichtig: Die rechte Grenze ist nicht enthalten im Ergebnis!
Wie das aussieht
int[] scores = { 10, 15, 8, 22, 17 };
int[] top3 = scores[0..3]; // Nimm die Elemente von 0 bis 2: {10, 15, 8}
- scores[0..3] — wir nehmen die Elemente ab Index 0 (inklusive) bis Index 3 (NICHT inklusive).
- Das Ergebnis-Array enthält die Elemente mit den Indizes 0, 1 und 2.
Abkürzungen
Wenn die linke Grenze fehlt, wird ab dem Anfang genommen:
int[] ersteZwei = scores[..2]; // das gleiche wie scores[0..2], also {10, 15}
Wenn die rechte Grenze fehlt, wird bis zum Ende genommen:
int[] abDrittem = scores[2..]; // {8, 22, 17}
Negative Indizes
Mit dem Symbol ^ kannst du Indizes vom Ende zählen:
int[] letzteZwei = scores[^2..]; // {22, 17}
Hier ist ^2 — das „zweite Element vom Ende“.
Du kannst auch einen Bereich „von bis“ nehmen, indem du negative Indizes auf beiden Seiten verwendest:
int[] mitte = scores[1..^1]; // {15, 8, 22} (vom zweiten bis zum vorletzten)
Was du dir merken solltest
- Das rechte Ende ist immer ausgeschlossen — also wenn du a..b schreibst, bekommst du alle Elemente von a bis b-1.
- Wenn du Grenzen angibst, die außerhalb des Arrays liegen, gibt's eine IndexOutOfRangeException.
- Ein Slice ist ein neues Array, das Original bleibt unverändert. Änderungen am neuen Array beeinflussen das Original nicht.
Praktische Beispiele
int[] arr = { 1, 2, 3, 4, 5, 6, 7 };
int[] arr = { 1, 2, 3, 4, 5, 6, 7 };
int[] start = arr[..3]; // {1, 2, 3}
int[] ende = arr[^2..]; // {6, 7}
int[] mitte = arr[2..5]; // {3, 4, 5}
int[] alles = arr[..]; // {1, 2, 3, 4, 5, 6, 7} (komplette Kopie)
GO TO FULL VERSION