Uno degli assembly fornito con l'installazione della Preview di LINQ è System.Query.dll. E' codice che gira sul .Net Framework 2.0 e pertanto può essere utilizzato e compilato anche con il compilatore C# 2.0 (lo stesso discorso vale per altri compilatori). C# 3.0 aggiunge diverse feature al compilatore che permettono ad es. di scrivere delegate con una sintassi compatta (lambda expression). L'esecutore del codice rimane comunque in ultima analisi il .Net Framework 2.0.
Curiosando nell'assembly si trovano diverse interessanti classi. Supponiamo ad es. di voler comporre programmaticamente una expressione che effettua la somma di due numeri interi. Possiamo scrivere una cosa del tipo:
using
System;
using System.Query;
using System.Expressions;
// ...
ParameterExpression param1 = Expression.Parameter(typeof(int), "x");
ParameterExpression param2 = Expression.Parameter(typeof(int), "y");
Expression body = Expression.Add(param1, param2);
Expression<Func<int, int, int>> expr = Expression.Lambda<Func<int, int, int>>(
body,
new ParameterExpression[] { param1, param2 }
);
StringBuilder sb = new StringBuilder();
expr.BuildString(sb);
Console.WriteLine(sb.ToString()); // (x, y) => Add(x, y)
Func<int, int, int> f = expr.Compile(); // Compila in codice IL la lambda expression!
Console.WriteLine(f(10, 3)); // 13 (esegue la lambda expression!)
In sostanza sto utilizzando le classi di System.Query e System.Expressions per scrivere a mano quello che il compilatore C# 3.0 scriverebbe al posto mio.
Diamo ora un'occhiata ad un'altra interessante classe:
LambdaExpression expr = QueryExpression.Lambda(
"x * y",
new ParameterExpression[]
{
Expression.Parameter(typeof(int), "x")
,Expression.Parameter(typeof(int), "y")
}
);
Delegate f = expr.Compile();
Console.WriteLine(f.DynamicInvoke(2, 4)); // 8
In questo caso il "body" della lambda expression non è più un oggetto di tipo espressione bensì una stringa! Il metodo Compile compila anche questa.