VB.NET List – Erstellen, Sortieren, Filtern (2026)
Die VB.NET List ist eine der meistgenutzten Datenstrukturen in der .NET-Entwicklung. Sie speichert Objekte in einer geordneten, dynamisch wachsenden Collection und bietet Methoden zum Hinzufügen, Entfernen, Sortieren und Suchen mit minimalem Code. Dieser Guide deckt alles ab: von der Erstellung über LINQ-Abfragen bis hin zu typischen Stolperfallen.
Inhaltsverzeichnis
Was ist eine List(Of T) und wann setzt man sie ein?
Eine List(Of T) ist eine generische Collection aus dem System.Collections.Generic-Namespace. Das T steht für den Typ der gespeicherten Objekte: List(Of String) speichert Strings, List(Of Integer) Zahlen, List(Of Customer) eigene Objekte.
Verwende eine List, wenn:
- Du eine geordnete Sammlung brauchst, in der Elemente eine Position (Index) haben
- Die Anzahl der Elemente sich zur Laufzeit ändert (anders als bei Arrays, die eine feste Größe haben)
- Du eingebaute Methoden zum Sortieren, Suchen und Filtern brauchst
- Du Elemente nach Position abrufst, nicht nach einem Schlüssel
Wenn du stattdessen Key-Value-Lookups brauchst (z.B. einen Kunden per ID finden), verwende ein VB.NET Dictionary. Listen durchsuchen jedes Element der Reihe nach, was bei großen Datenmengen langsam wird. Dictionaries finden Einträge in konstanter Zeit.
Eine List erstellen
Die gängigsten Wege, eine List(Of T) zu erstellen:
' Leere Liste
Dim names As New List(Of String)
' Liste mit Startwerten
Dim numbers As New List(Of Integer) From {3, 5, 7, 9}
' Liste mit eigenen Objekten
Dim customers As New List(Of Customer) From {
New Customer With {.Name = "Alice", .Email = "alice@example.com"},
New Customer With {.Name = "Bob", .Email = "bob@example.com"}
}
Das From-Keyword zusammen mit den geschweiften Klammern ist ein Collection Initializer. Im Hintergrund wird für jedes Element Add() aufgerufen.
Initiale Kapazität setzen
Wenn du ungefähr weißt, wie viele Elemente die Liste aufnehmen wird, setze die Kapazität im Voraus. Das vermeidet wiederholtes internes Array-Resizing:
' Platz für ca. 500 Elemente vorbelegen Dim largeList As New List(Of String)(500)
Das begrenzt die Liste nicht auf 500 Einträge. Es vermeidet nur unnötige Speicher-Allokationen, bis du diese Zahl überschreitest.
Elemente hinzufügen
Add und AddRange
Dim names As New List(Of String)
' Einzelne Elemente hinzufügen
names.Add("Alice")
names.Add("Bob")
' Mehrere Elemente auf einmal
names.AddRange({"Clara", "David", "Eva"})
' Elemente aus einer anderen Liste
Dim moreNames As New List(Of String) From {"Frank", "Grace"}
names.AddRange(moreNames)
An einer bestimmten Position einfügen
' "Zara" an Position 0 einfügen (Anfang) names.Insert(0, "Zara") ' An Position 2 einfügen names.Insert(2, "Maria")
Beachte, dass Insert() alle nachfolgenden Elemente verschiebt, was O(n) kostet. Für häufige Einfügungen am Anfang ist eine LinkedList(Of T) besser geeignet.
Auf Elemente zugreifen
Der Zugriff erfolgt über den nullbasierten Index:
Dim names As New List(Of String) From {"Alice", "Bob", "Clara"}
' Zugriff per Index
Dim first As String = names(0) ' "Alice"
Dim last As String = names(names.Count - 1) ' "Clara"
' Mit For Each iterieren
For Each name In names
Console.WriteLine(name)
Next
' Mit Index iterieren
For i As Integer = 0 To names.Count - 1
Console.WriteLine($"[{i}] {names(i)}")
Next
Ein ungültiger Index wirft eine ArgumentOutOfRangeException. Prüfe immer Count, bevor du einen bestimmten Index verwendest, oder nutze LINQ-Methoden wie FirstOrDefault().
Elemente entfernen
Dim names As New List(Of String) From {"Alice", "Bob", "Clara", "David"}
' Nach Wert entfernen (erstes Vorkommen)
names.Remove("Bob") ' gibt True zurück wenn gefunden
' Nach Index entfernen
names.RemoveAt(0) ' entfernt "Alice"
' Letztes Element entfernen
If names.Count > 0 Then
names.RemoveAt(names.Count - 1)
End If
' Alle Elemente entfernen, die eine Bedingung erfüllen
names.RemoveAll(Function(n) n.StartsWith("C"))
' Alles leeren
names.Clear()
Remove() durchsucht die Liste von vorne und entfernt den ersten Treffer. Wenn das Element nicht existiert, gibt die Methode False zurück, ohne eine Exception zu werfen. RemoveAt() bei einem ungültigen Index wirft hingegen eine Exception.
Eine Liste sortieren
Einfache Sortierung
Dim names As New List(Of String) From {"Clara", "Alice", "Bob"}
' Alphabetisch sortieren (in-place)
names.Sort()
' Ergebnis: Alice, Bob, Clara
' Reihenfolge umkehren
names.Reverse()
' Ergebnis: Clara, Bob, Alice
Eigene Sortierreihenfolge
Für eigene Objekte übergibst du einen Vergleichs-Lambda an Sort():
Public Class Contact
Public Property Name As String
Public Property Age As Integer
End Class
Dim contacts As New List(Of Contact) From {
New Contact With {.Name = "Clara", .Age = 30},
New Contact With {.Name = "Alice", .Age = 25},
New Contact With {.Name = "Bob", .Age = 35}
}
' Nach Name sortieren
contacts.Sort(Function(a, b) String.Compare(a.Name, b.Name))
' Nach Alter absteigend sortieren
contacts.Sort(Function(a, b) b.Age.CompareTo(a.Age))
Sortieren mit LINQ (nicht-destruktiv)
Sort() verändert die Originalliste. Wenn du eine neue sortierte Liste willst, ohne das Original zu ändern, verwende LINQ:
' Original bleibt unverändert Dim sorted = contacts.OrderBy(Function(c) c.Name).ToList() Dim sortedDesc = contacts.OrderByDescending(Function(c) c.Age).ToList()
Suchen und Filtern mit LINQ
LINQ ist der mächtigste Weg, Listen in VB.NET abzufragen. Importiere System.Linq (ist standardmäßig importiert) und du bekommst ein volles Set an Abfragemethoden:
Elemente finden
Dim contacts As New List(Of Contact) From {
New Contact With {.Name = "Alice", .Age = 25},
New Contact With {.Name = "Bob", .Age = 35},
New Contact With {.Name = "Clara", .Age = 30}
}
' Ersten Treffer finden (gibt Nothing zurück wenn nicht gefunden)
Dim alice = contacts.FirstOrDefault(Function(c) c.Name = "Alice")
' Prüfen ob irgendein Element passt
Dim hasOlderThan30 As Boolean = contacts.Any(Function(c) c.Age > 30)
' Prüfen ob alle Elemente passen
Dim allAdults As Boolean = contacts.All(Function(c) c.Age >= 18)
Elemente filtern
' Alle Kontakte älter als 25
Dim olderContacts = contacts.Where(Function(c) c.Age > 25).ToList()
' Nur die Namen extrahieren
Dim names = contacts.Select(Function(c) c.Name).ToList()
' Kombiniert: filtern + transformieren
Dim olderNames = contacts _
.Where(Function(c) c.Age > 25) _
.Select(Function(c) c.Name) _
.ToList()
Aggregat-Abfragen
' Count, Min, Max, Average, Sum Dim count As Integer = contacts.Count Dim youngest As Integer = contacts.Min(Function(c) c.Age) Dim oldest As Integer = contacts.Max(Function(c) c.Age) Dim averageAge As Double = contacts.Average(Function(c) c.Age) ' Unique Werte Dim uniqueAges = contacts.Select(Function(c) c.Age).Distinct().ToList()
Listen konvertieren
Listen lassen sich in andere Collection-Typen umwandeln und umgekehrt:
' Liste zu Array
Dim namesArray As String() = names.ToArray()
' Array zu Liste
Dim backToList As List(Of String) = namesArray.ToList()
' Liste zu Dictionary (Schlüssel muss eindeutig sein)
Dim contactDict = contacts.ToDictionary(
Function(c) c.Name,
Function(c) c)
' String aus Liste (zusammenfügen)
Dim csv As String = String.Join(", ", names)
' Ergebnis: "Alice, Bob, Clara"
Die ToDictionary()-Konvertierung ist besonders nützlich, wenn du später schnelle Lookups per Schlüssel brauchst. Mehr dazu im Dictionary Guide.
List vs. Array vs. Dictionary
Die Wahl der richtigen Collection ist entscheidend für Lesbarkeit und Performance. Hier ein Vergleich der gängigsten Typen:
| List(Of T) | Array | Dictionary(Of TKey, TValue) | |
|---|---|---|---|
| Größe | Dynamisch | Fest | Dynamisch |
| Zugriff per Index | O(1) | O(1) | N/A |
| Zugriff per Schlüssel | O(n) | O(n) | O(1) |
| Element hinzufügen | O(1) amortisiert | N/A (feste Größe) | O(1) amortisiert |
| Element entfernen | O(n) | N/A | O(1) |
| Ideal für | Geordnete Sammlungen, Iteration | Buffer fester Größe, Interop | Key-Value-Lookups |
Einen detaillierten Performance-Vergleich mit echten Benchmarks findest du im C# List Guide. Die Ergebnisse gelten genauso für VB.NET, da beide die gleiche .NET-Runtime verwenden.
Häufige Stolperfallen
Liste während der Iteration ändern
Das ist einer der häufigsten Anfängerfehler. Elemente innerhalb einer For Each-Schleife zu entfernen wirft eine InvalidOperationException:
' SCHLECHT - wirft InvalidOperationException!
For Each name In names
If name.StartsWith("A") Then
names.Remove(name)
End If
Next
' GUT - RemoveAll verwenden
names.RemoveAll(Function(n) n.StartsWith("A"))
' EBENFALLS GUT - rückwärts mit For iterieren
For i As Integer = names.Count - 1 To 0 Step -1
If names(i).StartsWith("A") Then
names.RemoveAt(i)
End If
Next
Liste für Lookups verwenden
Wenn du häufig Elemente nach einer eindeutigen Eigenschaft suchst (Name, ID, E-Mail), ist eine List die falsche Wahl. Jede Suche iteriert die gesamte Liste. Ein Dictionary findet das Element sofort. Der Unterschied wird bei Tausenden Einträgen massiv, wie in diesem Benchmark-Vergleich gezeigt.
ToList() vergessen
LINQ-Methoden wie Where() und Select() geben lazy IEnumerable-Objekte zurück, keine Listen. Jedes Mal wenn du iterierst, wird die Abfrage erneut ausgeführt. Ruf .ToList() auf, um das Ergebnis zu materialisieren:
' Lazy - führt den Filter zweimal aus! Dim filtered = names.Where(Function(n) n.Length > 3) Console.WriteLine(filtered.Count()) ' Filter läuft hier Console.WriteLine(filtered.Count()) ' Filter läuft nochmal ' Besser - einmal materialisieren Dim filteredList = names.Where(Function(n) n.Length > 3).ToList() Console.WriteLine(filteredList.Count) ' liest nur den Count Console.WriteLine(filteredList.Count) ' gleich, keine Neuauswertung
FAQ
Verwende Dim myList As New List(Of String) für eine leere Liste oder Dim myList As New List(Of String) From {"Alice", "Bob"} mit Startwerten. Ersetze String durch den Typ, den du brauchst.
Arrays haben eine feste Größe, die bei der Erstellung festgelegt wird. Listen wachsen und schrumpfen dynamisch mit Methoden wie Add() und Remove(). Verwende Arrays für Buffer fester Größe, Listen wenn sich die Anzahl ändern kann.
Rufe myList.Sort() für die Standardsortierung auf. Für eigene Objekte verwende ein Lambda: myList.Sort(Function(a, b) a.Name.CompareTo(b.Name)). LINQ OrderBy() erstellt eine neue Liste, ohne das Original zu ändern.
Verwende Remove(item) zum Entfernen nach Wert, RemoveAt(index) nach Position oder RemoveAll(Function(x) bedingung) für alle passenden Elemente. Entferne nie Elemente innerhalb einer For Each-Schleife.
Verwende ein Dictionary immer wenn du Elemente nach einem eindeutigen Schlüssel (Name, ID, E-Mail) suchen musst. Eine Liste muss jeden Eintrag durchlaufen (O(n)), während ein Dictionary in konstanter Zeit findet (O(1)).
Fazit
Die List(Of T) ist die Standard-Collection für geordnete, dynamische Daten in VB.NET. Verwende Add() und Remove() für Grundoperationen, Sort() mit einem Lambda für eigene Sortierung und LINQ für Filtern und Transformieren. Für schlüsselbasierte Lookups wechsle zum Dictionary. Die gleichen Konzepte gelten auch für C# mit leicht anderer Syntax, wie im C# List Guide gezeigt.