Der har været lavet en del usability studier omkring anvendelsen af lambdaudtryk i .NET. Feedback har været lambdaudtryk kan være temmelig svære at læse og skrive for manger OO-udviklere. Derfor er der lavet lidt syntaktisk sukker over lambdaudtryk, således de bliver lettere at læse/skrive. Resultatet er Query Expressions. Her er et par collections som jeg bruger til at lave en forespørgsel på:
List<Customer> customers = new List<Customer> { new Customer{Name="Henrik", Order=3},
new Customer{Name="Jeppe",Order=1}, new Customer{Name="Bo", Order=2}};
Dictionary<int, string> orders = new Dictionary<int, string> {
{1, "Silverlight 2.0"},{2, "All about management"}, {3, "More on F#"} };
I og med at de begge implementerer IEnumerable<T> så kan vi lave forespørgsler på dem, da der er lavet extension methods på IEnumerable<T> interfacet. En forespørgsel som joiner customers og orders ved hjælp af lambdaudtryk, projekterer customer.Name og order.Value ud, samt sorterer efter customer.Name ser ud som følgende:
var lambda = customers.Join( orders, cust => cust.Order,
order => order.Key,
(cust, order)=> new { Name = cust.Name, Order=order.Value })
.OrderBy(c=>c.Name);
Umiddelbart er jeg tilbøjelig til at give alle usability studierne ret – det er ikke særlig læsbart, hvis ikke man er vandt funktionelle programmeringssprog. Extension metoden Join tager 4 parametrer, hvor den første parameter er typen der skal joines (Dictonary orders), så gives en lambda der mapper joinnøglen til customer og efterfølgende en lambda der mapper joinnøglen i orders, og til sidst resultatet. Se MSDN dokumentationen for flere info.
Hvis man skal skrive ovenstående lambdaQuery om til at anvende Query Expressions, så vil det på mere læsevenlig form kunne skrives som følgende:
var query = from c in customers
join o in orders
on c.Order equals o.Key
orderby c.Name
select new { Name = c.Name, OrderText = o.Value };
Begge queries giver følgende resultat når jeg laver en foreach over dem:
{ Name = Bo, Order = All about management }
{ Name = Henrik, Order = More on F# }
{ Name = Jeppe, Order = Silverlight 2.0 }
Der er en meget bekvem .ToString() metode på anonyme typer således man kan udskrive alle properties på en anonym type.
Oftest plejer programmører at kløjes i syntaksen. Hvorfor kommer select til sidst og from først? Sådan gør man jo ikke i SQL?
For det første så er det ikke SQL, men LINQ. LINQ er et generelt forespørgselssprog som bruges mod mange datakilder og ikke kun relationelle databaser (her er det objekter). Desuden kan man sige, at i imperative programmeringssprog definerer man variabler før man bruger dem. Træerne vokser dog heller ikke ind i himlen. På et tidspunkt vil du nok lave et "fallback" til lambdaer, da det ikke er alle operatorer/extension methods der er implementeret. Jeg hører til den gruppe, der foretrækker lambdaer:-)
Her er lidt ressourcer hvis du vil læse mere om Query Expressions: