Lambda expressions

Ik moet zeggen, toen ik 2 jaar geleden voor het eerst een boek over Linq las en daar een heel stuk stond over Lambda expressions, dat ik halverwege wel even achter m’n oren moest krabben: wat is dat voor iets?
Maar zoals met alles, als je het meer en meer ziet ga je zelf ook wat proberen en gebruik ik nu de volgende 2 lambda’s regelmatig.
De ene is voor het selecteren van objecten uit een generic List op basis van een property van dat object, de andere is voor het ophalen van een lijst met de waardes van 1 property van die objecten (deze staat verderop in de blog ook al vermeld, maar voor de compleetheid toch nog even vermeld).

De case bij de eerste is: ik heb een lijst met keyword objecten. Deze hebben allemaal een property ‘rank’. Nu wil ik een lijst met alleen die keywords die minimaal een rankwaarde van 2 hebben. Daarvoor gebruikte ik altijd een mooie anonymous delegate die ik van m’n vriend en oud-collega René had geleerd (en het stond altijd wel biek, een anonymous delegate :-)) :
keywords.FindAll(delegate(Keyword m) { return m.Rank >= 2; });
Met een Lambda wordt het echter dit:
keywords.FindAll(m => m.Rank >= 2)
En dat is toch ook wel mooie code vind ik.

De case bij de 2e is: ik heb nog steeds die lijst met keyword objecten. Deze hebben naast de genoemde rank ook een value. En dat is waar ik op dit moment interesse in heb: in al die values. Ik heb dus een lijst met keyword objecten, en ik wil graag een lijst met strings gevuld hebben.
De oplossing zit in de ConvertAll methode:
List<string> values = keywords.ConvertAll(z => z.Value);

ps.
ik heb nog even opgezocht wat Microsoft eigenlijk zegt over een lambda expression:
A lambda expression is an anonymous function that can contain expressions and statements, and can be used to create delegates or expression tree types.

Lambda expressions op de generic list

Sinds C# 2.0 hebben we generic lists. Ik gebruik ze vrij vaak, want je kunt er zo lekker door for-eachen en het is strong typed etc.

Maar de methodes op zo’n list zoals Find, Exists, ConvertAll etc. nemen als parameter altijd een Predicate. En ik moet zeggen, zo’n predicate die je dan implementeert door een anonymous delegate, het was toch altijd weer even zoeken hoe je het ook alweer typt.  Zoals als je een lijst met objecten hebt van het type MissingOrderregel. Dat type heeft een veld RecordId en dat is nu precies het enige veld waarin je bent geïnteresseerd: je wilt eigenlijk alleen een lijst met RecordId waardes. Een manier is natuurlijk om met een foreach door de lijst heen te wandelen en dan van elk MissingOrderregel object de RecordId te nemen en die in een nieuwe lijst met Int32’s te stoppen.
Maar het kan ook anders:

Met een delegate doe je het zo:
List<int> recordids = regels.ConvertAll(delegate(MissingOrderregel z) { return z.RecordId; });

Maar, met de nieuwe mogelijkheid van Lambda expressions kun je ook dit typen:
List<int> recordids = regels.ConvertAll(z => z.RecordId);
Op de MSDN pagina staat dat je het moet lezen als ‘goes to‘, dus ‘z goes to z.RecordId‘.

 En zo kun je met die Lambda expressions ook gemakkelijk hele Lists casten van het ene type naar het andere (in dit voorbeeld wordt een hele List met Child objecten gecast naar een lijst met Parent objecten):
List<Parent> parents = childs.ConvertAll(z => (Parent)z);
z goes to z casted to a Parent type‘.