Ce face Enumerable.Select
Metoda Select este echivalentul funcției map din alte limbaje și al clauzei SELECT din SQL: primește o funcție de transformare (Func<TSource, TResult>) și produce câte un element de tip TResult pentru fiecare element TSource din secvența originală. Este folosită constant pentru a extrage o singură proprietate (de exemplu o listă de ID-uri sau de adrese de e-mail) ori pentru a converti entitățile din baza de date în obiecte DTO (Data Transfer Objects).
Atunci când fiecare element al colecției conține la rândul său o sub-colecție (de exemplu, fiecare Comanda conține un List<LinieComanda>), metoda pereche SelectMany proiectează și aplatizează (flattens) toate sub-listele într-o singură secvență continuă IEnumerable<LinieComanda>.
Parametri, metode și opțiuni
| Parametru / Metodă | Descriere |
|---|---|
source.Select(x => rezultat) |
Transformă fiecare element x în valoarea sau obiectul returnat de expresia lambda. |
source.Select((x, index) => rezultat) |
Include indexul elementului (începând de la 0) în funcția de transformare. |
source.SelectMany(x => x.SubColectie) |
Proiectează fiecare element într-o secvență și concatenează toate sub-secvențele într-o singură listă plată. |
source.Distinct() / DistinctBy(x => x.Cheie) |
Elimină elementele duplicate din secvență (sau duplicatele după o anumită proprietate în .NET 6+). |
source.Chunk(int size) |
Împarte secvența în loturi (tablouri T[]) de cel mult size elemente (.NET 6+). |
Exemple
Exemplul 1: Proiecția entităților în obiecte DTO cu Select și numerotare cu index
Transformăm o listă de angajați în rezumate pregătite pentru afișare, calculând salariul net și numărul de ordine.
var angajati = new[]
{
new Angajat("Elena Popa", "Backend .NET", SalariuBrut: 16000m),
new Angajat("Radu Ionescu", "DevOps", SalariuBrut: 18000m),
new Angajat("Maria Stan", "QA Automation", SalariuBrut: 12000m)
};
var fluturasi = angajati
.Select((a, idx) => new
{
Pozitie = idx + 1,
a.Nume,
a.Departament,
SalariuNet = Math.Round(a.SalariuBrut * 0.585m, 2)
})
.ToList();
foreach (var f in fluturasi)
{
Console.WriteLine($"#{f.Pozitie} {f.Nume} ({f.Departament}) -> Net: {f.SalariuNet:F2} RON");
}
record Angajat(string Nume, string Departament, decimal SalariuBrut);
Ieșire în consolă
#1 Elena Popa (Backend .NET) -> Net: 9360.00 RON
#2 Radu Ionescu (DevOps) -> Net: 10530.00 RON
#3 Maria Stan (QA Automation) -> Net: 7020.00 RON
Exemplul 2: Aplatizarea colecțiilor imbricate cu SelectMany și deduplicare cu Distinct
Extragem o listă unică cu toate tehnologiile folosite în mai multe proiecte folosind SelectMany urmat de Distinct.
var proiecte = new[]
{
new { Nume = "Portal Plăți", Tech = new[] { "C#", "PostgreSQL", "Docker" } },
new { Nume = "API Mobil", Tech = new[] { "C#", "Redis", "Docker" } },
new { Nume = "Worker Raport", Tech = new[] { "C#", "RabbitMQ" } }
};
string[] toateTehnologiile = proiecte
.SelectMany(p => p.Tech)
.Distinct()
.ToArray();
Console.WriteLine("Tehnologii unice: " + string.Join(", ", toateTehnologiile));
Ieșire în consolă
Tehnologii unice: C#, PostgreSQL, Docker, Redis, RabbitMQ
Greșeli frecvente
- Folosirea lui
Selectdoar pentru a produce efecte secundare (de exemplulista.Select(x => { Console.WriteLine(x); return x; });) — nu doar că încalcă principiul funcțional al luiSelect, dar dacă nu apelezi.ToList(), codul nici măcar nu se va executa din cauza evaluării leneșe. Folosește o buclăforeachobișnuită pentru efecte secundare. - Folosirea lui
Selectîn loc deSelectManype o proprietate care este deja o listă, obținând unIEnumerable<List<T>>(listă de liste) în loc de o listă platăIEnumerable<T>.
Funcții și concepte înrudite
Enumerable.Where: Filtrează declarativ o secvență de elemente pe baza unui predicat lambda, cu execuție amânată (deferred execution).OrderBy / ThenBy: Sortează secvențele crescător sau descrescător pe baza unuia sau mai multor criterii și extrage pagini cu Skip și Take.GroupBy: Grupează elementele unei secvențe după o cheie comună pentru a calcula statistici, sume și agregări pe categorii.record și imutabilitate: Definește într-o singură linie modele de date imutabile cu egalitate bazată pe valoare, afișare automată și clonare nedistructivă (with).