> ## Documentation Index
> Fetch the complete documentation index at: https://homelab.amylify.de/llms.txt
> Use this file to discover all available pages before exploring further.

# 4.2.5 Arrays & Collections

> Arrays, List, Dictionary und HashSet in C# sowie die Grundlagen von LINQ.

Oft hast du nicht einen Wert, sondern viele: Punkte, Namen, Preise. Dafür gibt es **Arrays** und **Collections**.

***

## Arrays

Ein **Array** hat eine **feste Größe** und enthält Werte desselben Typs. Der erste Index ist `0`.

```csharp theme={"dark"}
int[] zahlen = [10, 20, 30, 40];      // Collection-Ausdruck
string[] namen = new string[3];       // 3 leere Plätze (null)

zahlen[1] = 25;                       // Wert ändern
Console.WriteLine(zahlen[0]);         // 10
Console.WriteLine(zahlen.Length);     // 4
```

| Zugriff | Bedeutung |
| :- | :- |
| `zahlen[0]` | Erstes Element |
| `zahlen[^1]` | Letztes Element (`^` zählt von hinten) |
| `zahlen[1..3]` | Bereich: Index 1 bis ausschließlich 3 |
| `zahlen.Length` | Anzahl der Elemente |

> [!WARNING]
>
> Ein Index außerhalb des Arrays löst eine `IndexOutOfRangeException` aus. Bei vier Elementen ist `zahlen[4]` bereits ungültig.

### Durchlaufen und sortieren

```csharp theme={"dark"}
foreach (int z in zahlen)
{
    Console.WriteLine(z);
}

Array.Sort(zahlen);                    // aufsteigend sortieren
Array.Reverse(zahlen);                 // Reihenfolge umkehren
int position = Array.IndexOf(zahlen, 30);   // -1, wenn nicht gefunden
```

### Zweidimensionale Arrays

Ein Raster aus Zeilen und Spalten:

```csharp theme={"dark"}
int[,] raster = new int[3, 4];   // 3 Zeilen, 4 Spalten
raster[0, 2] = 7;

for (int zeile = 0; zeile < raster.GetLength(0); zeile++)
{
    for (int spalte = 0; spalte < raster.GetLength(1); spalte++)
    {
        Console.Write(raster[zeile, spalte] + " ");
    }
    Console.WriteLine();
}
```

***

## Welche Sammlung wofür?

| Typ | Eigenschaft | Typischer Einsatz |
| :- | :- | :- |
| `T[]` Array | Feste Größe, sehr schnell | Bekannte, feste Anzahl |
| `List<T>` | Wächst und schrumpft, Zugriff per Index | Standardwahl für Listen |
| `Dictionary<K, V>` | Schlüssel-Wert-Paare, schneller Zugriff per Schlüssel | Nachschlagen, Zuordnungen |
| `HashSet<T>` | Jeder Wert nur einmal | Duplikate vermeiden |
| `Queue<T>` | Zuerst hinein, zuerst heraus (FIFO) | Warteschlangen |
| `Stack<T>` | Zuletzt hinein, zuerst heraus (LIFO) | Rückgängig-Funktion |

> [!NOTE]
>
> `List<T>`, `Dictionary<K, V>` und die anderen liegen in `System.Collections.Generic`. In neuen Projekten ist dieser Namespace durch `ImplicitUsings` schon eingebunden. Das `<T>` ist ein **Typparameter**: `List<string>` ist eine Liste von Texten.

***

## List

```csharp theme={"dark"}
List<string> aufgaben = ["Einkaufen", "Lernen"];

aufgaben.Add("Sport");                // hinten anhängen
aufgaben.Insert(0, "Aufstehen");      // an Position einfügen
aufgaben.Remove("Lernen");            // nach Wert entfernen
aufgaben.RemoveAt(0);                 // nach Index entfernen

Console.WriteLine(aufgaben.Count);          // Anzahl (bei List: Count, nicht Length)
Console.WriteLine(aufgaben.Contains("Sport")); // true
aufgaben.Sort();                      // alphabetisch sortieren
```

| Methode | Wirkung |
| :- | :- |
| `Add(x)` | Hängt ein Element an |
| `Insert(i, x)` | Fügt an Position `i` ein |
| `Remove(x)` | Entfernt das erste Vorkommen von `x` |
| `RemoveAt(i)` | Entfernt das Element an Position `i` |
| `Contains(x)` | Prüft, ob `x` vorkommt |
| `IndexOf(x)` | Position oder `-1` |
| `Clear()` | Leert die Liste |
| `Sort()` | Sortiert aufsteigend |

***

## Dictionary

Ein `Dictionary` ordnet jedem **Schlüssel** genau einen **Wert** zu, wie ein Wörterbuch:

```csharp theme={"dark"}
Dictionary<string, int> alter = new()
{
    ["Mira"] = 28,
    ["Tom"] = 34
};

alter["Lea"] = 22;                       // neu hinzufügen
alter["Tom"] = 35;                       // vorhandenen Wert überschreiben

Console.WriteLine(alter["Mira"]);        // 28

if (alter.TryGetValue("Max", out int maxAlter))
{
    Console.WriteLine(maxAlter);
}
else
{
    Console.WriteLine("Max nicht gefunden");
}

foreach (var eintrag in alter)
{
    Console.WriteLine($"{eintrag.Key} ist {eintrag.Value}");
}
```

> [!WARNING]
>
> Greifst du mit `alter["Max"]` auf einen **nicht vorhandenen** Schlüssel zu, löst das eine `KeyNotFoundException` aus. Nutze `TryGetValue` oder prüfe vorher mit `ContainsKey`.

***

## HashSet

```csharp theme={"dark"}
HashSet<string> besucher = ["Mira", "Tom", "Mira"];

Console.WriteLine(besucher.Count);        // 2, "Mira" zählt nur einmal
Console.WriteLine(besucher.Add("Tom"));   // false, war schon vorhanden
```

***

## LINQ: Sammlungen abfragen

**LINQ** (Language Integrated Query) ist eine Sammlung von Methoden, mit denen du Daten filterst, sortierst und berechnest. Die Methoden stehen in `System.Linq`, das in neuen Projekten ebenfalls automatisch importiert wird.

```csharp theme={"dark"}
int[] zahlen = [5, 12, 8, 21, 3, 16];

var grosse = zahlen.Where(z => z > 10);          // 12, 21, 16
var verdoppelt = zahlen.Select(z => z * 2);      // 10, 24, 16, 42, 6, 32
var sortiert = zahlen.OrderBy(z => z);           // 3, 5, 8, 12, 16, 21

Console.WriteLine(zahlen.Sum());                 // 65
Console.WriteLine(zahlen.Average());             // 10,83...
Console.WriteLine(zahlen.Max());                 // 21
Console.WriteLine(zahlen.Any(z => z > 20));      // true
Console.WriteLine(zahlen.Count(z => z % 2 == 0)); // 3
```

| Methode | Wirkung |
| :- | :- |
| `Where(bedingung)` | Behält nur passende Elemente |
| `Select(umwandlung)` | Wandelt jedes Element um |
| `OrderBy` / `OrderByDescending` | Sortiert |
| `First()` / `FirstOrDefault()` | Erstes Element, die zweite Variante liefert sonst `null` oder `0` |
| `Any(...)` / `All(...)` | Trifft mindestens ein / jedes Element zu? |
| `Sum()` `Average()` `Min()` `Max()` `Count()` | Berechnungen |
| `ToList()` / `ToArray()` | Ergebnis in Liste oder Array umwandeln |

Die `=>`-Ausdrücke sind **Lambdas** (siehe [Methoden](https://homelab.amylify.de/documentation/code/csharp/methoden.md)). Methoden lassen sich verketten:

```csharp theme={"dark"}
List<string> namen = ["Mira", "Tom", "Lea", "Maximilian"];

List<string> ergebnis = namen
    .Where(n => n.Length > 3)
    .OrderBy(n => n)
    .ToList();

Console.WriteLine(string.Join(", ", ergebnis));   // Maximilian, Mira
```

> [!NOTE]
>
> LINQ-Abfragen werden meist erst ausgeführt, wenn du das Ergebnis tatsächlich brauchst, zum Beispiel in `foreach` oder bei `ToList()`.

***

## Weiter

> [card] [4.2.6 Objektorientierung](https://homelab.amylify.de/documentation/code/csharp/oop.md)
>
> Eigene Typen mit Daten und Verhalten bauen.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.