CodeGym /Corsi /C# SELF /Introduzione a LINQ e i suoi vantaggi

Introduzione a LINQ e i suoi vantaggi

C# SELF
Livello 31 , Lezione 0
Disponibile

1. Introduzione

Immagina di entrare in una biblioteca e dover trovare tutti i libri di programmazione pubblicati dopo il 2020, ordinati per nome dell’autore. Difficilmente correresti da uno scaffale all’altro controllando ogni libro a mano, giusto? Chiederesti al bibliotecario, che sa come trovare velocemente quello che ti serve.

LINQ (Language Integrated Query, cioè "Query integrate nel linguaggio") – è il nostro "bibliotecario intelligente", un "motore SQL" (cioè uno strumento per scrivere query sui dati) direttamente dentro C#!

Pensa a LINQ come a un linguaggio che ti permette di descrivere cosa vuoi ottenere dai dati, non come farlo. Invece di dire: "Prendi il primo elemento, controlla la condizione, se va bene aggiungilo a una nuova lista, poi passa al secondo...", dici semplicemente: "Dammi tutti i prodotti con prezzo superiore a 1000". E C# si occupa di capire come farlo nel modo più efficiente.

Idea chiave di LINQ: fornire una sintassi standard per le query su qualsiasi fonte dati che implementa l’interfaccia IEnumerable<T>. Ed è fantastico, perché List<T>, array, HashSet<T> – tutti implementano IEnumerable<T>. E se i tuoi dati sono in un database, librerie speciali (tipo Entity Framework) trasformano le tue query LINQ in vero SQL!

LINQ è arrivato in C# più di 10 anni fa. È stato un evento epocale che ha cambiato il modo di lavorare con i dati in .NET. Prima di LINQ, gli sviluppatori dovevano scrivere un sacco di codice boilerplate per filtrare, ordinare e trasformare le collezioni. Oppure usare stringhe SQL, che non venivano controllate dal compilatore e potevano causare errori a runtime. LINQ ha portato il concetto di "query" direttamente nel linguaggio di programmazione, rendendole type-safe e più leggibili.

Molti pensano che LINQ sia una delle innovazioni più importanti in C# dai tempi dei Generics.

2. Vantaggi di LINQ: Perché tutti lo amano?

Codice breve e leggibile: Per filtrare, ad esempio, prodotti con prezzo superiore a 1000 in un grande database, prima dovevi scrivere diverse righe di codice. Con LINQ puoi farlo in una sola. Meno codice — meno possibilità di errori, più leggibilità e chiarezza. Il codice diventa più vicino al linguaggio naturale.
Battuta da programmatore: "Più poco codice scrivo, meno bug posso infilarci dentro." LINQ aiuta proprio in questo!

Potenza e flessibilità: LINQ offre un set ricco di operazioni: filtraggio (Where), proiezione (Select), ordinamento (OrderBy), raggruppamento (GroupBy), aggregazione (Sum, Average), join (Join) e molto altro. Ti permette di risolvere problemi complessi di manipolazione dati combinando queste operazioni.

Type-safety: È importantissimo! Quando scrivi una query SQL come stringa, il compilatore non ne sa nulla. Se sbagli il nome di una colonna, lo scopri solo a runtime, quando l’applicazione crasha. Con LINQ il compilatore C# controlla la tua query già in fase di compilazione. Se provi a chiedere un campo che non esiste in Product, il compilatore ti segnala subito l’errore. È come avere un correttore personale che trova i tuoi typo prima che li vedano gli altri.

Integrazione col linguaggio: Le query LINQ non sono "magiche" stringhe. Sono vere e proprie costruzioni C#, che usano le lambda expressions che già conosci e lavorano con i tipi di dati familiari. Questo rende il passaggio a LINQ molto naturale.

Esecuzione differita (Deferred Execution): Questa è una delle cose più fighe e forse più difficili di LINQ, ma è fondamentale. In pratica, una query LINQ non viene eseguita subito appena la scrivi. Viene "preparata" e aspetta che tu chieda davvero il risultato (ad esempio, quando la iteri con foreach). Questo permette di ottimizzare le query, soprattutto con grandi quantità di dati. Ne parleremo meglio nella Lezione 166. Per ora tienilo a mente: LINQ è smart, non fa lavoro inutile.

Universalità ed estendibilità: LINQ non è solo per le liste in memoria. Esistono diversi "provider" LINQ:

  • LINQ to Objects: per collezioni in memoria (List<T>, array, ecc.).
  • LINQ to SQL / Entity Framework Core: per database SQL (le tue query LINQ vengono trasformate in query SQL).
  • LINQ to XML: per lavorare con documenti XML.
  • E molti altri.
    Questo significa che, imparando LINQ, puoi lavorare con dati da fonti diversissime usando la stessa logica di query.

3. Il problema di lavorare con le collezioni "alla vecchia maniera"

Prima di LINQ, il codice per lavorare con le collezioni in C# era più o meno così:


var products = new List<Product> { /* ... */ };

var expensive = new List<Product>();
foreach (var prod in products)
{
    if (prod.Price > 100)
        expensive.Add(prod);
}

expensive.Sort((a, b) => a.Price.CompareTo(b.Price));

foreach (var item in expensive)
    Console.WriteLine(item.Name);

Questo approccio è tipico: prima filtri a mano, poi ordini — e devi creare una lista intermedia. Più logica, più codice, più errori e variabili. Sembra un laboratorio di falegnameria: hai i pezzi, ma il montaggio è tutto manuale e faticoso.

Alice nel paese dei cicli

Immagina di avere una lista enorme di utenti e vuoi solo i nomi di quelli che hanno più di 18 anni e vivono nella città di Neonville, ordinarli alfabeticamente e prendere i primi tre. Dovresti scrivere cicli annidati, condizioni, ordinamenti, liste di appoggio... oppure semplicemente usare LINQ.

4. Come appare una query LINQ? Esempi semplici

LINQ offre due sintassi principali:

  • Method Syntax (catena di metodi)
  • Query Syntax (linguaggio simile a SQL)

Di solito si usa Method Syntax, soprattutto nei progetti moderni. Ecco un esempio basato sulla nostra app:


var expensive = products
    .Where(p => p.Price > 100)
    .OrderBy(p => p.Price)
    .Select(p => p.Name)
    .Take(3);

foreach (var name in expensive)
    Console.WriteLine(name);

Tutto chiaro: filtro, ordinamento, selezione del campo, limite di quantità. Minimo codice — massimo senso.

Lo stesso con Query Syntax


var expensive = from p in products
                where p.Price > 100
                orderby p.Price
                select p.Name;

foreach (var name in expensive.Take(3))
    Console.WriteLine(name);

Entrambe le versioni danno lo stesso risultato — scegli quella che preferisci (ma il method syntax è più usato).

5. Architettura LINQ: cosa c’è sotto il cofano?

LINQ funziona con qualsiasi collezione che implementa l’interfaccia IEnumerable<T> (o IQueryable<T>, di cui parleremo più avanti).

Componenti principali di LINQ

Componente Descrizione breve
Classi di estensione LINQ Metodi statici (
Where
,
Select
,
OrderBy
ecc.) nella classe
System.Linq.Enumerable
Delegate Di solito si usano
Func<T, TResult>
e
Predicate<T>
Esecuzione differita La query viene valutata solo al primo ciclo (ad esempio con
foreach
)
Query Provider (per LINQ to SQL, LINQ to Entities) — trasforma la catena di metodi in query SQL ecc.

Schema visuale


Collezione (List<Product>, T[], ...) 
      │
      ▼
Metodi LINQ (Where, OrderBy, Select...)
      │
      ▼
Query (IEnumerable<T>) 
      │
      ▼
Esecuzione reale (foreach, ToList, Count, ...)

6. Esempio: analisi step-by-step di una catena LINQ nella nostra app

Torniamo alla nostra mini-app con la classe Product:


// Classe prodotto
class Product
{
    public string Name { get; set; }
    public double Price { get; set; }
}

Ecco una lista di prodotti:


var products = new List<Product>
{
    new Product { Name = "Formaggio", Price = 250.5 },
    new Product { Name = "Pane", Price = 30 },
    new Product { Name = "Latte", Price = 80 },
    new Product { Name = "Caffè", Price = 330 },
    new Product { Name = "Burro", Price = 140 }
};

Supponiamo che il nostro compito sia: stampare a schermo i nomi di tutti i prodotti con prezzo superiore a 100 euro, ordinati per prezzo.

Metodo vecchio


var filtered = new List<Product>();
foreach (var p in products)
{
    if (p.Price > 100)
        filtered.Add(p);
}

filtered.Sort((a, b) => a.Price.CompareTo(b.Price));

foreach (var p in filtered)
    Console.WriteLine(p.Name);

Metodo LINQ


var expensive = products
    .Where(p => p.Price > 100)
    .OrderBy(p => p.Price)
    .Select(p => p.Name);

foreach (var name in expensive)
    Console.WriteLine(name);

Nella prima riga descriviamo proprio l’essenza del compito: "Filtra quelli con Price > 100, ordina per prezzo, prendi i nomi".

7. Operazioni LINQ frequenti e i loro equivalenti "alla vecchia maniera"

Operazione Logica "alla vecchia" LINQ
Filtraggio foreach + if + Add
Where
Proiezione (selezione campo) foreach + Add(field)
Select
Ordinamento Sort(comparer)
OrderBy
,
OrderByDescending
Valori unici foreach + contains + Add
Distinct
Conteggio foreach + counter++
Count
,
Count(predicate)
Controllo condizione foreach + if
Any
,
All
Trova primo/ultimo foreach + if + break
First
,
Last
,
FirstOrDefault
Limitare quantità foreach + contatore + break
Take
,
Skip

8. Pratica: aggiungiamo LINQ all’app

Prendiamo il codice base della nostra app (lista di Product) e proviamo a realizzare alcune operazioni utili con LINQ.

Filtraggio e ordinamento


// Seleziona prodotti con prezzo inferiore a 200 euro e ordina per nome
var cheapProducts = products
    .Where(p => p.Price < 200)
    .OrderBy(p => p.Name);

foreach (var p in cheapProducts)
    Console.WriteLine($"{p.Name}: {p.Price} euro");

Trasformazione (proiezione) della collezione


// Ottieni la lista dei prezzi (double)
var prices = products.Select(p => p.Price);

foreach (var price in prices)
    Console.WriteLine(price);

Trova il primo elemento che corrisponde


// Primo prodotto il cui nome inizia con "C"
var firstK = products.FirstOrDefault(p => p.Name.StartsWith("C"));
Console.WriteLine(firstK?.Name ?? "Non trovato");

Conta i prodotti con prezzo superiore a 100 euro


int count = products.Count(p => p.Price > 100);
Console.WriteLine($"Prodotti così: {count} pz.");

Da questa lezione useremo LINQ attivamente per lavorare con le collezioni, filtrare, selezionare dati, aggregare e molto altro. Nuovi metodi e possibilità di LINQ (anche le novità di .NET 9!) li vedremo nelle prossime lezioni, ma intanto — non aver paura di sperimentare con query semplici per sentire tutta la potenza di questo strumento!

Commenti
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION