List în C# (.NET)

Colecții generice .NET 2.0+ (collection expressions [..] în C# 12+)

Stochează o listă generică redimensionabilă dinamic, cu acces rapid după index și metode de adăugare, ștergere și căutare.

Sintaxă C#
List<string> lista = ["a", "b"]; lista.Add("c");

Ce face List<T>

Clasa System.Collections.Generic.List<T> este cea mai utilizată colecție din .NET: reprezintă un tablou dinamic puternic tipizat care își dublează automat capacitatea internă pe măsură ce adaugi elemente cu Add() sau AddRange(). Oferă acces în timp constant O(1) la orice element după index (lista[i]) și adăugare în timp amortizat O(1) la sfârșitul listei.

În C# 12 (.NET 8+), poți inițializa o listă folosind sintaxa concisă de collection expressions cu paranteze drepte (List<int> scoruri = [10, 20, 30];) și poți îmbina mai multe colecții într-una singura prin operatorul spread ([.. listaVeche, 40, 50]).

Parametri, metode și opțiuni

Parametru / Metodă Descriere
Add(T item) / AddRange(IEnumerable<T>) Adaugă un element sau o întreagă secvență de elemente la sfârșitul listei.
Insert(int index, T item) Inserează elementul la poziția index, deplasând la dreapta elementele următoare (O(n)).
Remove(T item) / RemoveAt(int index) Șterge prima apariție a lui item sau elementul aflat la poziția index.
RemoveAll(Predicate<T> match) Șterge eficient toate elementele care îndeplinesc condiția lambda și returnează numărul de elemente eliminate.
Find(Predicate<T>) / Exists(Predicate<T>) Găsește primul element care respectă condiția sau verifică dacă există cel puțin unul.
Sort() / Count / Capacity Sortează lista in-place, returnează numărul actual de elemente (Count) sau dimensiunea bufferului intern (Capacity).

Exemple

Exemplul 1: Inițializare cu collection expressions (C# 12), adăugare și filtrare in-place

Folosim sintaxa [..] din C# 12 pentru a combina două liste, apoi eliminăm elementele nedorite direct din listă cu RemoveAll.

List<string> echipaBackend = ["Andrei", "Elena"];
List<string> echipaCompleta = [.. echipaBackend, "Mihai", "Ioana", "Dan"];

echipaCompleta.Add("Vlad");
echipaCompleta.Remove("Mihai");

// Eliminăm toți membrii cu numele mai scurt de 4 caractere:
int eliminati = echipaCompleta.RemoveAll(nume => nume.Length < 4);

echipaCompleta.Sort();
Console.WriteLine($"Membri ({echipaCompleta.Count}, eliminați {eliminati}): {string.Join(", ", echipaCompleta)}");

Ieșire în consolă

Membri (4, eliminați 1): Andrei, Elena, Ioana, Vlad

Exemplul 2: Căutarea și sortarea personalizată a unei liste de obiecte

Metoda Sort acceptă o expresie lambda de comparare, iar Find returnează primul element care corespunde criteriului.

var sarcini = new List<Sarcina>
{
    new("Migrare bază de date", Prioritate: 2),
    new("Fix autentificare OAuth", Prioritate: 1),
    new("Actualizare documentație", Prioritate: 3)
};

// Sortare crescătoare după prioritate (1 = maximă):
sarcini.Sort((a, b) => a.Prioritate.CompareTo(b.Prioritate));

foreach (var s in sarcini)
{
    Console.WriteLine($"[P{s.Prioritate}] {s.Titlu}");
}

Sarcina? urgenta = sarcini.Find(s => s.Prioritate == 1);
Console.WriteLine($"Prima urgență: {urgenta?.Titlu}");

record Sarcina(string Titlu, int Prioritate);

Ieșire în consolă

[P1] Fix autentificare OAuth
[P2] Migrare bază de date
[P3] Actualizare documentație
Prima urgență: Fix autentificare OAuth

Greșeli frecvente

  • Modificarea listei (apelând lista.Remove(x) sau lista.Add(x)) în interiorul unei bucle foreach (var x in lista), ceea ce aruncă imediat InvalidOperationException: Collection was modified; enumeration operation may not execute. Pentru ștergere după o condiție folosește lista.RemoveAll(x => ...) sau parcurge lista invers cu un for.
  • Confuzia între proprietatea .Count (folosită pe List<T>, Dictionary, HashSet) și .Length (folosită pe tablouri T[] și pe string).

Funcții și concepte înrudite

  • Dictionary<TKey, TValue>: Stochează perechi cheie-valoare într-o tabelă de dispersie (hash table) cu căutare, inserare și ștergere în timp constant O(1).
  • HashSet<T>: Menține o mulțime neordonată de elemente unice cu verificare de apartenență în timp O(1) și operații matematice pe mulțimi.
  • Array și Span<T>: Lucrează cu blocuri contigue de memorie și felii (slices) de înaltă performanță fără alocări suplimentare pe heap.
  • Enumerable.Where: Filtrează declarativ o secvență de elemente pe baza unui predicat lambda, cu execuție amânată (deferred execution).