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âiif (filtrate.Any())și apoiforeach (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 luiWherepe care EF Core nu le poate traduce în SQL, ceea ce aruncăInvalidOperationExceptionla 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.