BizTalk Utilities CV ,   Jobs ,   Code library
 
Go to the front page to continue learning about XML or select below:

Contents

ReBlogger Contents

Previous posts in XML

 
 
Page 3742 of 16798

C# 3.0: Lambdaudtryk

Blogger : MSDN Blogs
All posts : All posts by MSDN Blogs
Category : XML
Blogged date : 2007 Nov 19

Lambdaudtryk (?) er formentlig den mest interessante nyhed i C# 3.0, eller i det hele taget på .NET 3.5. Lambdaudtryk er kendt fra funktionelle programmeringssprog som LISP, Scheme, Haskell, ML og F# som nu bliver en del af .NET. Det er super interessant at funktionelle og imperative programmeringsparadigmer møder hinanden. Formålet med at bringe lambdaudtryk ind i C# har i udgangspunktet været at løse "impedance mismatch" problemet. Impedance mismatch problemet er kort sagt problemet med, at vi i dag har mange forskellige typesystemer og representationer af data (f.eks. relationelle data, XML, objekter). Interaktionen mellem typesystemerne er besværligt og fejlbehæftiget (se denne video med Anders Hejlsberg).

Endnu mere interessant bliver det, på længere sigt, at integrationen af funktionelle principper vil blive en programmeringsmodel for multi-core/CPU programmering (se denne video med Anders Hejlsberg og Joe Duffy om PLINQ/PFX). Det betyder at lambdarfunktioner er noget vi kommer til at se meget mere til ;-)

Hvad er lambdaudtryk: lambdaudtryk er "bare" syntaktisk sukker over anonyme metoder. Anonyme metoder blev implementeret i C# 2.0. Hvis du forstår anonyme metoder og delegates, så er du så godt som i mål med lambda'er:-)

For de af jer der ikke har arbejdet med anonyme metoder, hvilket der er rigtig mange der ikke har endnu, så er her et lille eksempel på en anonym metode:

public
delegate int ADelegate(int a, int b);
class Lambdas
{
    public int Add(int a, int b)
    { return a + b; }

    public void Exec()
    {
        //den gode gamle delegate
        ADelegate del = Add;
        //kald af delegate
        int result = del(40, 2);
        //definer ny anonym metode - så kan den deklarerede Add metode undværes.
        del = delegate(int a, int b) { return a + b; };
        //kald den nye anonyme metode
        result = del(19, 2);
     }
}
Jeg bruger altså Add delegaten til at lægge to tal sammen. Efterfølgende laver jeg en anonym metode, hvor jeg genbruger del variablen som er af typen ADelegate.

Selve den anonyme metode kan omskrives til en lambda:

//en "gammel" C# 2.0 anonym metode
del = delegate(int a, int b) { return a + b; };
//lambda med eksplicitte parametre, samt et body med {} og return
del = (int a, int b) => { return a + b; };
//typerne er udledes gennem inferens (del er en ADelegate<int>),
//return og {} kan undlades da der kun er et statement.
del = (a, b) => a + b;


I ovenstående kan du se hvordan de forskellige literaler/parametre mapper mellem lambdaen og den anonyme metode. Input er på venstresiden af => og metodekroppen på højreside. Du kan, som i en anonym metode, skrive så mange linjer i en lambdafunktion som du har lyst til. Ved mere en et statement, skal du bruge start og slut { }, samt eksplicit returnere.

Med C# 2.0 kom også generics. Ovenstående delegate kan ved hjælp af generics omskrives til:

public delegate T ADelegate<T>(T a, T b);

Fordi delegaten er lavet generisk, kan vi også bruge den med andre typer:

ADelegate<string> Concat = (a, b) => a + " " + b;
string myString = Concat("Hello", "World");

I C# 3.0 er en række generiske delegates allerede lavet for dig, som tager op til fire input parametre (T1 til T4) og har en retur parameter (TResult):

public delegate TResult Func<T, TResult>(T arg);
public delegate TResult Func<T1, T2, TResult>(T1 arg1, T2 arg2);       
public delegate TResult Func<T1, T2, T3, TResult>(T1 arg1, T2 arg2, T3 arg3);
public delegate TResult Func<T1, T2, T3, T4, TResult>(T1 arg1, T2 arg2, T3 arg3, T4 arg4);   

Det vil sige, at jeg kan omskrive Add og Concat metoder til at anvende de predefinerede delegates:

Func<string, string, string> Concat = (a, b) => a + " " + b;
Func<int, int, int> Add = (a, b) => a + b;

Lambdaer kan frit bruges inde fra andre metoder og lambdaer.

Func<int, bool> Even = a => (a % 2) == 0;
Func<int, int, bool> AddResultIsEven = (a, b) => Even(Add(a, b));
var r = AddResultIsEven(2, 2);

Den første lambda i ovenstående er en predikatfunktion som returnerer true eller false (sidste parameter i delegaten Func er en bool). Den sidste lambda anvender både Add og Even lambdafunktionerne.

Lambdafunktioner bruges i C# 3.0 bl.a. til at lave LINQ forespørgsler med. Jeg har tidligere gennemgået extension methods. Kort sagt så er LINQ (to Objects) lavet ved at implementere extension methods på IEnumerable<T>. Where er en extension method på IEnumerable<T>. Nedenstående kodelinje er signaturen til Where predikatet.

public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate);

Parameteren this IEnumerable<TSource> source deklarerer at det er IEnumerable<T> der skal extendes, og anden parameter tager en lambdafunktion af typen Func<TSource, bool>, altså et predikat. Det vil sige, at alle collections der implementerer IEnumerable<T> kan drage nytte af alle LINQ metoderne, hvis man inkluderer System.Linq namespace'et.

Afslutningsvis er her et eksempel på, hvordan man kan filtrere på en liste af stenge ved hjælp af lambdaudtryk:

List<string> l = new List<string> {
    "Hello", "World",
    "Henrik", "Hansen",
    "And", "Some", "More" };
string search = "H";
Func<string,bool> pred = a => a.StartsWith(search);
var query = l.Where(a => pred(a));
foreach (var item in query)
    Console.WriteLine(item);


Read comments or post a reply to : C# 3.0: Lambdaudtryk
Page 3742 of 16798

Newest posts
 

    Email TopXML