LINQ - Espressioni Lambda
Il termine "espressione lambda" ha derivato il suo nome da "lambda" calcolo che a sua volta è una notazione matematica applicata per definire le funzioni. Le espressioni Lambda come parte eseguibile di un'equazione LINQ traducono la logica in un modo in fase di esecuzione in modo che possa passare comodamente all'origine dati. Tuttavia, le espressioni lambda non si limitano solo a trovare applicazioni solo in LINQ.
Queste espressioni sono espresse dalla seguente sintassi:
(Input parameters) ⇒ Expression or statement block
Ecco un esempio di un'espressione lambda:
y ⇒ y * y
L'espressione sopra specifica un parametro denominato y e il valore di y è al quadrato. Tuttavia, non è possibile eseguire un'espressione lambda in questa forma. Di seguito è riportato un esempio di un'espressione lambda in C #.
C #
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace lambdaexample {
class Program {
delegate int del(int i);
static void Main(string[] args) {
del myDelegate = y ⇒ y * y;
int j = myDelegate(5);
Console.WriteLine(j);
Console.ReadLine();
}
}
}
VB
Module Module1
Private Delegate Function del(ByVal i As Integer) As Integer
Sub Main(ByVal args As String())
Dim myDelegate As del = Function(y) y * y
Dim j As Integer = myDelegate(5)
Console.WriteLine(j)
Console.ReadLine()
End Sub
End Module
Quando il codice precedente di C # o VB viene compilato ed eseguito, produce il seguente risultato:
25
Espressione Lambda
Poiché l'espressione nella sintassi dell'espressione lambda mostrata sopra si trova sul lato destro, questi sono noti anche come espressione lambda.
Async Lambdas
L'espressione lambda creata incorporando l'elaborazione asincrona mediante l'uso della parola chiave async è nota come lambda asincrona. Di seguito è riportato un esempio di lambda asincrono.
Func<Task<string>> getWordAsync = async()⇒ “hello”;
Lambda negli operatori di query standard
Un'espressione lambda all'interno di un operatore di query viene valutata dallo stesso su richiesta e lavora continuamente su ciascuno degli elementi nella sequenza di input e non sull'intera sequenza. Agli sviluppatori è consentito dall'espressione Lambda di alimentare la propria logica negli operatori di query standard. Nell'esempio seguente, lo sviluppatore ha utilizzato l'operatore "Where" per recuperare i valori dispari dall'elenco fornito utilizzando un'espressione lambda.
C #
//Get the average of the odd Fibonacci numbers in the series...
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace lambdaexample {
class Program {
static void Main(string[] args) {
int[] fibNum = { 1, 1, 2, 3, 5, 8, 13, 21, 34 };
double averageValue = fibNum.Where(num ⇒ num % 2 == 1).Average();
Console.WriteLine(averageValue);
Console.ReadLine();
}
}
}
VB
Module Module1
Sub Main()
Dim fibNum As Integer() = {1, 1, 2, 3, 5, 8, 13, 21, 34}
Dim averageValue As Double = fibNum.Where(Function(num) num Mod 2 = 1).Average()
Console.WriteLine(averageValue)
Console.ReadLine()
End Sub
End Module
Quando il codice precedente viene compilato ed eseguito, produce il seguente risultato:
7.33333333333333
Digitare Inference in Lambda
In C #, l'inferenza del tipo viene utilizzata convenientemente in una varietà di situazioni e anche senza specificare i tipi in modo esplicito. Tuttavia, nel caso di un'espressione lambda, l'inferenza del tipo funzionerà solo quando ogni tipo è stato specificato poiché il compilatore deve essere soddisfatto. Consideriamo il seguente esempio.
delegate int Transformer (int i);
Qui il compilatore utilizza l'inferenza del tipo per attingere al fatto che x è un numero intero e questo viene fatto esaminando il tipo di parametro del Transformer.
Ambito variabile nell'espressione Lambda
Esistono alcune regole durante l'utilizzo dell'ambito variabile in un'espressione lambda come le variabili che vengono avviate all'interno di un'espressione lambda non sono pensate per essere visibili in un metodo esterno. Esiste anche una regola per cui una variabile acquisita non deve essere raccolta in Garbage Collection a meno che il delegato che fa riferimento alla stessa non diventi idoneo per l'atto di Garbage Collection. Inoltre, esiste una regola che proibisce a un'istruzione return all'interno di un'espressione lambda di causare la restituzione di un metodo di inclusione.
Di seguito è riportato un esempio per dimostrare l'ambito della variabile nell'espressione lambda.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace lambdaexample {
class Program {
delegate bool D();
delegate bool D2(int i);
class Test {
D del;
D2 del2;
public void TestMethod(int input) {
int j = 0;
// Initialize the delegates with lambda expressions.
// Note access to 2 outer variables.
// del will be invoked within this method.
del = () ⇒ { j = 10; return j > input; };
// del2 will be invoked after TestMethod goes out of scope.
del2 = (x) ⇒ { return x == j; };
// Demonstrate value of j:
// The delegate has not been invoked yet.
Console.WriteLine("j = {0}", j); // Invoke the delegate.
bool boolResult = del();
Console.WriteLine("j = {0}. b = {1}", j, boolResult);
}
static void Main() {
Test test = new Test();
test.TestMethod(5);
// Prove that del2 still has a copy of
// local variable j from TestMethod.
bool result = test.del2(10);
Console.WriteLine(result);
Console.ReadKey();
}
}
}
}
Quando il codice precedente viene compilato ed eseguito, produce il seguente risultato:
j = 0
j = 10. b = True
True
Albero delle espressioni
Le espressioni lambda vengono utilizzate in Expression Treecostruzione ampiamente. Un albero delle espressioni fornisce codice in una struttura dati simile a un albero in cui ogni nodo è esso stesso un'espressione come una chiamata a un metodo o può essere un'operazione binaria come x <y. Di seguito è riportato un esempio di utilizzo dell'espressione lambda per la costruzione di un albero delle espressioni.
Istruzione Lambda
C'è anche statement lambdasconsistono di due o tre affermazioni, ma non vengono utilizzati nella costruzione di alberi di espressione. Un'istruzione return deve essere scritta in un'istruzione lambda.
Sintassi dell'istruzione lambda
(params)⇒ {statements}
Esempio di un'istruzione lambda
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;
namespace lambdaexample {
class Program {
static void Main(string[] args) {
int[] source = new[] { 3, 8, 4, 6, 1, 7, 9, 2, 4, 8 };
foreach (int i in source.Where(x ⇒
{
if (x <= 3)
return true;
else if (x >= 7)
return true;
return false;
}
))
Console.WriteLine(i);
Console.ReadLine();
}
}
}
Quando il codice precedente viene compilato ed eseguito, produce il seguente risultato:
3
8
1
7
9
2
8
Lambda vengono utilizzati come argomenti nelle query LINQ basate su metodi e non è mai consentito di avere un posto sul lato sinistro di operatori come is o asproprio come i metodi anonimi. Sebbene le espressioni Lambda siano molto simili ai metodi anonimi, questi non sono affatto limitati all'uso solo come delegati.
Punti da ricordare durante l'utilizzo di espressioni lambda
Un'espressione lambda può restituire un valore e può avere parametri.
I parametri possono essere definiti in una miriade di modi con un'espressione lambda.
Se è presente una singola istruzione in un'espressione lambda, non è necessario utilizzare parentesi graffe mentre se sono presenti più istruzioni, è essenziale scrivere le parentesi graffe e il valore restituito.
Con le espressioni lambda, è possibile accedere alle variabili presenti all'esterno del blocco di espressioni lambda tramite una funzionalità nota come chiusura. L'uso della chiusura dovrebbe essere fatto con cautela per evitare qualsiasi problema.
È impossibile eseguire codice non sicuro all'interno di qualsiasi espressione lambda.
Le espressioni lambda non sono pensate per essere utilizzate sul lato sinistro dell'operatore.