CodeGym /Corsi /C# SELF /Sintassi delle espressioni lambda (

Sintassi delle espressioni lambda ( =>)

C# SELF
Livello 49, Lezione 1
Disponibile

1. Introduzione

Potresti non saperlo, ma una delle domande preferite ai colloqui è “Cosa sai delle espressioni lambda?”. Perché la chiedono? Perché è una feature molto comoda e "alla moda" in C#, che permette di scrivere meno codice e renderlo più espressivo. Se i metodi anonimi sono come scrivere una lettera a mano, le espressioni lambda sono come mandare un messaggio su un messenger: veloce, compatto e a volte anche con emoji (beh, quasi).

Le espressioni lambda sono arrivate in C# con la versione 3.0 e da allora si sono diffuse ovunque: in LINQ, negli handler di eventi, nei thread, nelle collezioni e persino nelle librerie di AI su .NET.

Un'espressione lambda è un modo per dichiarare un metodo direttamente nel corpo del codice, "sul posto", senza nome, super conciso e chiaro. La sintassi base è sempre così:

(parametri) => espressione_o_blocco_di_codice

Questo "segno" => si chiama “operatore lambda” o “freccia”.

Una piccola analogia

Ricorda come scrivi una ricetta: “Prendere una mela, tagliarla, metterla nella ciotola”.
In C# sarebbe:

(mela) => tagliare(mela)

2. Trasformiamo un metodo anonimo in una lambda

Supponiamo di avere un delegato:

delegate int SquareDelegate(int x);

Il metodo anonimo apparirebbe così:

SquareDelegate sq = delegate(int x) {
    return x * x;
};

E ora lo stesso usando un'espressione lambda:

SquareDelegate sq = (int x) => { return x * x; };

Ma C# può inferire i tipi, e possiamo accorciare ancora:

SquareDelegate sq = x => x * x;

Che compattezza fantastica!

Confronto con un metodo "normale" e una funzione anonima

Modalità Dichiarazione Dove si può usare Svantaggi
Metodo nominato In una classe Ovunque Serve un nome, più codice
Metodo anonimo Nel codice Solo con delegati Sintassi più verbosa
Espressione lambda Nel codice Ovunque con delegati Talvolta il tipo non è ovvio

3. Sintassi dell'espressione lambda: varianti

Parametri

Senza parametri:

Action hello = () => Console.WriteLine("Ciao, mondo!");

Un parametro (puoi omettere le parentesi):

Func<int, int> inc = x => x + 1;

Più parametri (servono le parentesi):

Func<int, int, int> sum = (a, b) => a + b;

Corpo della lambda

Una singola espressione — senza parentesi graffe e senza return:

x => x * x

Blocco di codice — parentesi graffe, serve il return:

(x, y) =>
{
    int z = x + y;
    return z * z;
}

Tipi dei parametri

Di solito non serve specificare i tipi — il compilatore li deduce. Ma se vuoi, puoi:

(x, y) => x + y      // Il compilatore inferisce i tipi.
(int x, int y) => x + y  // Puoi specificarli esplicitamente.

4. Sfumature e esempi più realistici

Uso con le collezioni

Ricorda la nostra mini-app didattica (per esempio, una lista di utenti)? Supponiamo di avere un array di numeri:

int[] numbers = { 1, 2, 3, 4, 5 };

Vogliamo selezionare solo i numeri pari:

var evenNumbers = numbers.Where(n => n % 2 == 0);

Qui Where è un metodo di estensione LINQ, e la condizione è il nostro filtro lambda.

Passare come parametro a un metodo

Supponiamo di avere un metodo delegato:

public delegate bool Filter(int number);

public static int[] FilterNumbers(int[] data, Filter predicate)
{
    var result = new List<int>();
    foreach (var n in data)
        if (predicate(n))
            result.Add(n);
    return result.ToArray();
}

Ora passiamo un'espressione lambda:

int[] evens = FilterNumbers(numbers, n => n % 2 == 0);

Lambda come gestore di eventi

button.Click += (sender, args) => Console.WriteLine("Pulsante premuto!");

5. Lambda e i delegati generici standard

È difficile immaginare le lambda senza Func<>, Action<> e Predicate<>. Sono tipi speciali di delegati:

  • Action — non restituisce nulla.
  • Func — restituisce un valore.
  • Predicate — restituisce bool, di solito per filtrare.

Esempio con Action:

Action<string> log = message => Console.WriteLine(message);

log("Questo è un messaggio via lambda!");

Esempio con Func:

Func<int, int, int> multiply = (a, b) => a * b;
int product = multiply(3, 5); // 15

Esempio con Predicate:

Predicate<int> isNegative = n => n < 0;

bool test = isNegative(-7); // true

6. Lambda con più espressioni: quando serve il blocco

Se la lambda deve eseguire più operazioni, usa le parentesi graffe e il return esplicito:

Func<int, int, string> describeSum = (a, b) =>
{
    int sum = a + b;
    return $"Somma: {sum}";
};

Senza return il compilatore si lamenterà (ma non spiegherà tanto bene il perché — dirà semplicemente che "non tutti i percorsi ritornano un valore").

7. Restituire void: Action

Quando la lambda non restituisce nulla, usa Action:

Action greet = () => Console.WriteLine("Sorridi — il codice compila!");

La lambda può contenere quante istruzioni vuoi:

Action<int> printSquare = x =>
{
    int sq = x * x;
    Console.WriteLine($"Il quadrato di {x} è {sq}");
};

8. Limitazioni ed errori tipici

A volte vorresti scrivere la lambda in modo molto libero, ma il compilatore non sempre è d'accordo.

Non puoi dichiarare una variabile con lo stesso nome di una catturata dall'esterno.

Fai attenzione ai tipi: se la firma del delegato e quella della lambda non coincidono, ci sarà un errore.

Il ritorno di un valore è obbligatorio se il delegato richiede un valore di ritorno.

In lambda complesse non dimenticare le parentesi graffe. Una singola espressione — senza graffe e senza return. Più istruzioni — graffe e return.

2
Compito
C# SELF, livello 49, lezione 1
Bloccato
Espressione lambda con più parametri per sommare numeri
Espressione lambda con più parametri per sommare numeri
Commenti
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION