C# 3.0: Extension Methods

C# 3.0: Extension Methods

Rate This
  • Comments 7

Extension Methods er en af de nye grundlæggende sprogudvidelser der kommer med C# 3.0. Extension methods bruges i stor stil til at implementere LINQ funktionaliteten i .NET 3.5. Extension methods er statiske metoder, som du kan kalde med standard instansmetode syntaks. Extension methods er udelukkende et kompiler trick. Lad os kigge på et par scenarier hvor det vil være interessant at bruge extension methods.

sealed class Developer
{
   public string FirstName{ get; set; }
   public string LastName{ get; set; }
  
public int ProgrammingExperience{ get; set; }
}
Antag nu at du har brug for at udvide Developer klassen med en metode, der siger noget om hvorvidt en Developer er erfaren. I eksemplet har man den mulighed at lave en wrapper-klasse da Developer ikke kan nedarves. Havde Developer ikke været sealed, så kunne man selvfølgelig have lavet en nedarvning. Begge løsninger betyder, at du ville være nødsaget til at oprette en ny klasse, udelukkende med det formål at tilføje funktionalitet til den oprindelige Developer klasse (det er altså ikke en ny type developer der er tale om, for så havde nedarvning været det rigtige). En tredje hurtig løsning ville være, at lave en static klasse som kunne indeholde metoden der udregner hvorvidt en developer er erfaren eller ej. Ingen af disse løsninger er særlig pæn/ren objektorientering.

Ved brug af extension methods kan du tilføje "statiske instans-metoder". Extension methods laves som følgende:

static class MyExtensions
{
   public static bool Experienced(this Developer p)
   {
      return (p.ProgrammingExperience > 5) ? true : false;
   }
}
Klasse og metode skal være static, i selve signaturen bruges this, således kompileren ved, at den skal lave lidt ekstra arbejde med netop Developer objektet. Det betyder, at du nu kan kalde Experienced på alle  Developer objekter, som var det en instansmetode:

Bemærk det lille ikon som illustrerer at det er en extension method. Forvirringen ville være stor hvis ikke det var meget synligt hvilke metoder der er extension methods.

Et andet eksempel kan være, at du måske har behov for yderligere metoder på en primitiv type – hvem har f.eks. ikke hele tiden brug for en Fibonacci metode på den primitive type int:

static class MyFibExtensions{
   public static IEnumerable<int> Fib(this int f)
   {
      int firstFib = 0;
      int secondFib = 1;
      int temp;
      while (true)
      {
         yield return firstFib;
         temp = firstFib;
         firstFib = secondFib;
         checked
         {
            try
            { secondFib = temp + secondFib; }
            catch (OverflowException)
            { break; }
         }
      }
   }
   public static bool IsAFib(this int f)
   {
      bool isFib = false;
      foreach (int i in 0.Fib())
      {
         if (i == f)
         { isFib = true; break; }
         else if (i > f)
         { isFib = false; break; };
      }
   return isFib;
   }
}

Der er også et par nævneværdige C# 2.0 ting med i ovenstående extension methods; iteratorer som benytter sig af den generiske type IEnumerable<T> samt yield return keywordet, og checked keywordet som bruges til boundry check af alle variable i scoope.

Nu kan du bruge Fibonacci på int. Følgende udskriver alle fibonacci tal som i int samt udskriver hvorvidt 5 er indeholdt i fibonaccitalrækken.

static void Main(string[] args)
{
   foreach (int i in 0.Fib())
   {
      Console.WriteLine(i);
   }
  
Console.WriteLine(5.IsAFib());
}
 

Jeg kan klart anbefale ScottGu's blog… igen. Scott har skrevet en god udførlig post om extension methods hvis du vil vide mere.

  • I stedet for at skrive

    return (p.ProgrammingExperience > 5) ? true : false;

    ville jeg nøjes med

    return p.ProgrammingExperience > 5;

    Der er ikke nogen grund til at skrive mere kode end højst nødvendigt - og slet ikke på en søndag ;-)

  • First of all, I really can't understand the language used in your post, well except... C# :). I also have to admit that your post introduced me with the concept of extensions. But I would like to comment smth:

    If a method declaration, has only one argument [this int f] like the next one,

    public static bool IsAFib(this int f)

    it would make sense that this method will become a *property* of the class instead of a _method_. e.g.

    bool fib = 3.IsAFib;

    instead of

    bool fib 3.IsAFib();

    Thank you!

    P.S. Sorry about my bad :( english.

  • Hej Henrik, god post og godt at se noget om extension methods.

    Der er lige en ting som jeg syntes bliver glemt lidt. Der er flere der har påpeget at extension methods i nogle tilfælde kan "misbruges" og også gøre code-reviews og debugging en smule sværere. Jeg syntes personligt at man skal bestræbe sig på at holde brugen af extension methods til et minimum eller i hvert fald tænke sig rigtig godt om inden man implementerer en... Især hvis man udvikler klassebiblioteker der skal bruges af andre.

    Men bare rolig jeg syntes bestemt også at der er gode eksempler på brug at extension methods... bare tag et kig på dem der følger med frameworket.

  • God post Henrik!

    Havde ikke lige hørt om Exstension Methods før din post - så det skal da hjem og prøves af.

    Og der er helt klart nogle steder hvor jeg kan komme til at bruge dem.

    //Ronnie

  • Hi Henrik,

    Nice meeting you at techtalks this week.  I am also interested in functional programming languages, and am looking into F#.

    This article published in Dr. Dobbs Journal today may interest you. www.ddj.com

    regards

    Scott Hill

    frontier sciences group

    Functional Languages: Into the Real World

    A knock against functional programming languages typically involves their inoperability with nonfunctional languages, which lead to impedance mismatches between data and objects. Hence, their slow adoption in the mainstream of software development. But considering the growing complexity of today's software systems and the fact that modularity--like that of functional languages--is the key to successful programming, functional languages have a lot to offer when tackling multi-core and parallel computing.

    Which is probably one reason why Microsoft has decided to move its F# functional programming language from the research labs into the real world. Specifically, F# will be a first-class citizen on .NET, integrate into Visual Studio, and run on the Common Language Runtime (CLR). Which means, in other words, that it will interoperate with other languages.

    Of course, playing around with functional languages isn't new to Microsoft. Functional language features such as lambda expressions are in C#, and generics are in .NET 2.0. And LINQ, a set of .NET extensions for language-integrated queries, is directly based on functional programming techniques, at least according to Anders Hejlsberg, chief architect of C#, in this video entitled Anders Hejlsberg on LINQ and Functional Programming.

    Functional languages like F#, which has its roots in ML, have other benefits, including type safety, performance, and interactive scripting on modern runtimes. And again, it is ideal for taking on complex problems, like those in the financial, scientific, and technical computing arenas.

    For a better explanation of why functional programming is important, take a look at Why Functional Programming Matters, by John Hughes.

    -- Jonathan Erickson

    jerickson@ddj.com

  • N&#229;r man begynder at arbejde lidt med polygoner i WPF, s&#229; syntes jeg hurtigt at man m&#248;der

  • Parallel Extensions er et bud på at lave en programmeringsmodel der understøtter multi-core og CPU programmering.

Page 1 of 1 (7 items)