Espressioni lambda

Scegliere un'espressione lambda quando si vuole passare un'operazione breve a un altro metodo e l'operazione è più chiara accanto alla chiamata che la usa. Una regola inline mostra ai lettori come si selezionano o trasformano gli elementi; un metodo denominato consente di seguire lo scopo dell'operazione prima di esaminarne i dettagli.

Tip

Questo articolo illustra le scelte pratiche per gli sviluppatori che conoscono metodi e raccolte di C#. Per la sintassi lambda completa e le regole, vedere le informazioni di riferimento sulle espressioni lambda.

Un'espressione lambda è una funzione senza nome che scrivi dove un'altra parte di codice richiede un comportamento.

L'espressione lambda seguente accetta una sessione e restituisce se la sessione dispone di posti disponibili:

session => session.Registered < session.Capacity

L'operatore => separa i parametri a sinistra dal corpo a destra. Leggilo come "va a".

Passare il comportamento a un metodo

Molte API .NET accettano un delegate, ovvero un tipo che rappresenta un comportamento con un particolare elenco di parametri e un tipo di ritorno. Un'espressione lambda fornisce tale comportamento. Per un'introduzione ai tipi delegati, come Func e Action, vedere Espressioni lambda, delegati ed eventi.

L'esempio seguente funziona con sessioni di workshop. Un WorkshopSession oggetto contiene un titolo, una durata, una capacità e un conteggio delle registrazioni.

int maximumMinutes = 60;

var shortSessions = sessions
    .Where(session => session.DurationMinutes <= maximumMinutes)
    .OrderBy(session => session.Title);

foreach (WorkshopSession session in shortSessions)
{
    Console.WriteLine(session.Title);
}

La prima espressione lambda specifica a Where le sessioni da mantenere. Il secondo indica OrderBy il valore in base al quale eseguire l'ordinamento. I metodi ricevono il comportamento senza conoscere i dettagli di nessuna delle due regole.

Scegliere un modulo parametro

Scegliere il formato di parametro più breve che rimane chiaro:

session => session.DurationMinutes <= 60

Per un parametro, omettere le parentesi quando il compilatore può dedurre il tipo. Usare parentesi vuote senza parametri:

() => DateTime.Now

Usare le parentesi per due o più parametri:

(left, right) => left + right

In genere, il metodo che riceve l'espressione lambda fornisce informazioni sufficienti per il compilatore per dedurre i tipi di parametro. Scrivere tipi espliciti quando l'inferenza richiede assistenza o quando i tipi migliorano la chiarezza:

(WorkshopSession session) => session.Title

Il riferimento alle espressioni lambda include modificatori di parametri, attributi, valori predefiniti e altre forme specializzate.

Scegliere un'espressione o il corpo di un'istruzione

Usare un'espressione lambda quando un'espressione calcola il risultato:

session => session.Registered < session.Capacity

Usare una lambda con corpo di istruzioni quando l'operazione richiede più di un'istruzione. Racchiudere il corpo tra parentesi graffe e includere return quando l'espressione lambda restituisce un valore:

var descriptions = sessions.Select(session =>
{
    int seatsLeft = session.Capacity - session.Registered;
    string availability = seatsLeft > 0 ? $"{seatsLeft} seats left" : "full";
    return $"{session.Title}: {availability}";
});

Console.WriteLine(string.Join(Environment.NewLine, descriptions));

Mantenere brevi le lambda di istruzione. Quando il corpo richiede più passaggi o la stessa logica compare più di una volta, assegnare un nome descrittivo al comportamento con una funzione locale o un metodo regolare.

Acquisire valori dall'ambito circostante

Un'espressione lambda può usare una variabile dichiarata nel metodo circostante. Questo uso viene chiamato capture. Nel primo esempio, l'espressione lambda di selezione cattura maximumMinutes:

int maximumMinutes = 60;
var shortSessions = sessions.Where(
    session => session.DurationMinutes <= maximumMinutes);

Capture aiuta una breve regola a usare il contesto locale. L'espressione lambda acquisisce la variabile stessa, non una copia del relativo valore. Se la variabile cambia prima dell'esecuzione dell'espressione lambda, l'espressione lambda vede il valore corrente.

Rendi facile identificare il contesto necessario. Se una lambda non richiede lo stato circostante, aggiungere static per impedire l'acquisizione accidentale e rendere tale indipendenza visibile ai lettori:

var openSessions = sessions.Where(
    static session => session.Registered < session.Capacity);

Un'espressione lambda statica può usare i parametri, i valori che dichiara, le costanti e i membri statici. Non può usare variabili locali o lo stato dell'istanza dal codice circostante.

Scegliere una funzione lambda, un gruppo di metodi o una funzione locale

Diverse forme C# possono fornire il comportamento a un parametro delegate:

  • Usare un'espressione lambda per un comportamento breve facilmente leggibile accanto alla chiamata.
  • Usare un method group quando un metodo esistente ha la firma necessaria e il relativo nome spiega il comportamento.
  • Usare una funzione locale quando il membro contenitore necessita di logica denominata riutilizzabile, ricorsione o corpo troppo grande per un'espressione lambda inline.
  • Usare un metodo normale quando più membri necessitano del comportamento.

Un gruppo di overload è un nome di metodo senza il relativo elenco di argomenti. Il compilatore converte il metodo corrispondente nel tipo delegato richiesto:

var openSessions = sessions.Where(HasOpenSeats);

foreach (WorkshopSession session in openSessions)
{
    Console.WriteLine($"Open: {session.Title}");
}

static bool HasOpenSeats(WorkshopSession session) =>
    session.Registered < session.Capacity;

Where(HasOpenSeats) comunica la stessa regola di Where(session => HasOpenSeats(session)) con meno codice. Il nome del metodo indica ai lettori che cosa verifica la regola; un confronto inline mostra come testa tale regola. Mantenere il wrapper lambda quando aggiunge un argomento, combina le operazioni o rende la chiamata più chiara.

Per un confronto locale dettagliato, vedere Funzioni locali.

Vedere anche