Enumerable.Where în C# (.NET)

LINQ (Language Integrated Query) .NET 3.5+ / C# 3.0+

Filtrează declarativ o secvență de elemente pe baza unui predicat lambda, cu execuție amânată (deferred execution).

Sintaxă C#
var filtrate = colectie.Where(x => conditie);

Ce face Enumerable.Where

Metoda de extensie Where din System.Linq.Enumerable este pilonul de filtrare din LINQ: primește o funcție predicat (Func<TSource, bool>) și returnează o nouă secvență IEnumerable<TSource> care conține doar elementele pentru care expresia lambda returnează true. Colecția sursă nu este niciodată modificată.

O caracteristică fundamentală a lui Where este execuția amânată (deferred execution): apelul var rezultat = lista.Where(x => x.Activ); nu parcurge lista imediat, ci construiește doar un iterator ușor. Filtrarea propriu-zisă se execută abia atunci când parcurgi secvența într-un foreach sau când apelezi o metodă de materializare precum .ToList(), .ToArray() sau .Count().

Parametri, metode și opțiuni

Parametru / Metodă Descriere
source.Where(x => predicat) Păstrează în secvența rezultată doar elementele x pentru care expresia booleană predicat este true.
source.Where((x, index) => predicat) Suprascriere care oferă și indexul (de la 0) al fiecărui element din secvența sursă.
source.OfType<TResult>() Filtrează o colecție eterogenă păstrând doar elementele care pot fi convertite la tipul TResult.
.ToList() / .ToArray() Forțează evaluarea imediată a interogării LINQ și stochează rezultatele într-un List<T> sau T[] în memorie.

Exemple

Exemplul 1: Filtrarea produselor după stoc și categorie cu înlănțuire LINQ

Putem combina mai multe condiții cu && într-un singur Where sau putem înlănțui mai multe apeluri Where succesive.

var produse = new List<Produs>
{
    new("Laptop Pro 14", "IT", 5400m, Stoc: 4),
    new("Mouse Optic", "Accesorii", 85m, Stoc: 0),
    new("Monitor IPS 27", "IT", 1350m, Stoc: 7),
    new("Tastatură USB", "Accesorii", 120m, Stoc: 12),
    new("Server Rack", "IT", 18500m, Stoc: 2)
};

var oferteIt = produse
    .Where(p => p.Categorie == "IT" && p.Stoc > 0 && p.Pret <= 6000m)
    .ToList();

foreach (var p in oferteIt)
{
    Console.WriteLine($"{p.Denumire} - {p.Pret} RON (stoc: {p.Stoc})");
}

record Produs(string Denumire, string Categorie, decimal Pret, int Stoc);

Ieșire în consolă

Laptop Pro 14 - 5400 RON (stoc: 4)
Monitor IPS 27 - 1350 RON (stoc: 7)

Exemplul 2: Filtrarea cu acces la indexul elementului și execuție amânată

A doua semnătură a metodei Where((element, index) => ...) permite selectarea elementelor aflate pe poziții pare sau impare.

string[] orase = ["București", "Cluj-Napoca", "Timișoara", "Iași", "Brașov", "Constanța"];

// Păstrăm doar elementele de pe poziții pare (index 0, 2, 4):
var pozitiiPare = orase.Where((oras, index) => index % 2 == 0);

Console.WriteLine("Orașe pe poziții pare: " + string.Join(", ", pozitiiPare));

Ieșire în consolă

Orașe pe poziții pare: București, Timișoara, Brașov

Greșeli frecvente

  • Enumerarea multiplă a unui IEnumerable<T> nematerializat (de exemplu, apelând mai întâi if (filtrate.Any()) și apoi foreach (var x in filtrate)) — din cauza execuției amânate, filtrul (sau interogarea SQL/API subiacentă) se va executa de două ori! Apelează .ToList() dacă intenționezi să parcurgi rezultatul de mai multe ori.
  • În Entity Framework Core (IQueryable<T>), apelarea unor metode C# personalizate în interiorul lui Where pe care EF Core nu le poate traduce în SQL, ceea ce aruncă InvalidOperationException la rulare.

Funcții și concepte înrudite

  • Enumerable.Select: Proiectează (transformă) fiecare element al unei secvențe într-o formă nouă și aplatizează colecțiile imbricate cu SelectMany.
  • FirstOrDefault / SingleOrDefault: Extrage un singur element dintr-o secvență (primul găsit sau unicul existent) ori returnează o valoare implicită când nu există potriviri.
  • Any, All, Count și Sum: Evaluează condiții booleene rapide (cu scurtcircuitare) și calculează agregări numerice (Count, Sum, Average, Min, Max) peste colecții.
  • List<T>: Stochează o listă generică redimensionabilă dinamic, cu acces rapid după index și metode de adăugare, ștergere și căutare.