C# Language
Espressioni Lambda
Ricerca…
Osservazioni
Un'espressione lambda è una sintassi per la creazione di funzioni anonime in linea. Più formalmente, dalla Guida alla Programmazione C # :
Un'espressione lambda è una funzione anonima che è possibile utilizzare per creare delegati o tipi di albero di espressioni. Utilizzando espressioni lambda, è possibile scrivere funzioni locali che possono essere passate come argomenti o restituite come valore delle chiamate di funzione.
Un'espressione lambda viene creata usando l'operatore =>
. Metti tutti i parametri sul lato sinistro dell'operatore. Sul lato destro, metti un'espressione che può usare quei parametri; questa espressione si risolverà come valore di ritorno della funzione. Più raramente, se necessario, un intero {code block}
può essere utilizzato sul lato destro. Se il tipo di reso non è nullo, il blocco conterrà un'istruzione di reso.
Passare un'espressione lambda come parametro di un metodo
List<int> l2 = l1.FindAll(x => x > 6);
Qui x => x > 6
è un'espressione lambda che funge da predicato che assicura che vengano restituiti solo gli elementi superiori a 6.
Lambda Expressions come abbreviazione per l'inizializzazione dei delegati
public delegate int ModifyInt(int input);
ModifyInt multiplyByTwo = x => x * 2;
La sintassi di espressione Lambda di cui sopra è equivalente al seguente codice verboso:
public delegate int ModifyInt(int input);
ModifyInt multiplyByTwo = delegate(int x){
return x * 2;
};
Lambda sia per `Func` che per` Action`
Tipicamente i lambda sono usati per definire semplici funzioni (generalmente nel contesto di un'espressione linq):
var incremented = myEnumerable.Select(x => x + 1);
Qui il return
è implicito.
Tuttavia, è anche possibile passare azioni come lambda:
myObservable.Do(x => Console.WriteLine(x));
Espressioni Lambda con parametri multipli o nessun parametro
Utilizza le parentesi intorno all'espressione a sinistra dell'operatore =>
per indicare più parametri.
delegate int ModifyInt(int input1, int input2);
ModifyInt multiplyTwoInts = (x,y) => x * y;
Allo stesso modo, un insieme vuoto di parentesi indica che la funzione non accetta parametri.
delegate string ReturnString();
ReturnString getGreeting = () => "Hello world.";
Metti più dichiarazioni in una dichiarazione Lambda
A differenza di un'espressione lambda, una dichiarazione lambda può contenere più istruzioni separate da punto e virgola.
delegate void ModifyInt(int input);
ModifyInt addOneAndTellMe = x =>
{
int result = x + 1;
Console.WriteLine(result);
};
Si noti che le istruzioni sono racchiuse tra parentesi {}
.
Ricorda che l'istruzione lambda non può essere utilizzata per creare alberi di espressione.
Lambdas può essere emesso sia come `Func` che come` Expression`
Supponendo la seguente classe Person
:
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
Il seguente lambda:
p => p.Age > 18
Può essere passato come argomento per entrambi i metodi:
public void AsFunc(Func<Person, bool> func)
public void AsExpression(Expression<Func<Person, bool>> expr)
Perché il compilatore è in grado di trasformare lambda sia in delegati che in Expression
.
Ovviamente, i provider LINQ fanno molto affidamento su Expression
s (esposti principalmente attraverso l'interfaccia IQueryable<T>
) al fine di essere in grado di analizzare le query e tradurle per memorizzare le query.
Espressione Lambda come gestore di eventi
Le espressioni Lambda possono essere utilizzate per gestire eventi, il che è utile quando:
- Il gestore è corto.
- Il gestore non deve mai essere annullato.
Di seguito viene fornita una buona situazione in cui è possibile utilizzare un gestore di eventi lambda:
smtpClient.SendCompleted += (sender, args) => Console.WriteLine("Email sent");
Se è necessario annullare la sottoscrizione di un gestore di eventi registrato in un punto futuro del codice, l'espressione del gestore di eventi deve essere salvata in una variabile e la registrazione / annullamento della registrazione eseguita tramite tale variabile:
EventHandler handler = (sender, args) => Console.WriteLine("Email sent");
smtpClient.SendCompleted += handler;
smtpClient.SendCompleted -= handler;
La ragione per cui questo è fatto piuttosto che semplicemente ridigitare l'espressione lambda letteralmente per cancellarla ( -=
) è che il compilatore C # non considererà necessariamente le due espressioni uguali:
EventHandler handlerA = (sender, args) => Console.WriteLine("Email sent");
EventHandler handlerB = (sender, args) => Console.WriteLine("Email sent");
Console.WriteLine(handlerA.Equals(handlerB)); // May return "False"
Si noti che se vengono aggiunte istruzioni addizionali all'espressione lambda, le parentesi graffe circostanti richieste possono essere omesse accidentalmente, senza causare errori in fase di compilazione. Per esempio:
smtpClient.SendCompleted += (sender, args) => Console.WriteLine("Email sent"); emailSendButton.Enabled = true;
Questo verrà compilato, ma comporterà l'aggiunta dell'espressione lambda (sender, args) => Console.WriteLine("Email sent");
come gestore di eventi ed esecuzione della dichiarazione emailSendButton.Enabled = true;
subito. Per risolvere questo problema, il contenuto del lambda deve essere racchiuso tra parentesi graffe. Questo può essere evitato usando le parentesi graffe dall'inizio, facendo attenzione quando si aggiungono ulteriori istruzioni a un gestore di eventi lambda o circondando il lambda in parentesi tonde dall'inizio:
smtpClient.SendCompleted += ((sender, args) => Console.WriteLine("Email sent"));
//Adding an extra statement will result in a compile-time error