h1

.NET 3.5 – Neuerungen bei C#3.0 – Teil 3 von 9

August 20, 2007

Extension-Methods
Extension Methods erweitern den Kontrakt für bestehende Klassen, ohne dass der Code der bestehenden Klassen verändert wird oder von der Klasse eine Ableitung erzeugt wird. Extension-Methods werden beim compilieren durch den Compiler aufgelöst, wenn der Namespace in dem die Extension-Method definiert wurde an der gewünschten Stelle eingebunden wurde.

Hier das erste einfache Beispiel:

namespace ExtensionMethods {
 public static class Extensions {
   public static string EliminateWhiteSpace(this string param) {
     return param.Replace(' ', string.Empty);
   }
 }
}

--> Verwendung:

using ExtensionMethods;

namespace ConsoleApplication {
  class Program {
    static void Main(string[] args) {
      Console.WriteLine("Hallo Welt!".EliminateWhiteSpace());
      Console.ReadLine();
    }
  }
}

Dank des „using ExtensionMethods;“ wird der Compiler keinen Fehler melden, denn der Compiler macht daraus:

Console.WriteLine(Extensions.EliminateWhiteSpace("Hallo Welt!"));

Dieses erste Beispiel zeigt schon sehr viele Regeln die bei der Verwendung von Extension-Methods beachtet werden müssen:

  1. Die Klasse in der eine Extension-Method erstellt wird, muss static sein. Das gleiche gild für die Extension-Method selber.
  2. Der erste Parameter in einer Extension-Method wird mit dem Modifier this versehen und entspricht dem Typ auf dem die Extension-Method angewendet werden kann.
  3. Instanz-Methoden haben immer vor Extension-Methods Vorrang. Es kann also keine vorhanden Funktion durch eine Extension-Method ersetzt werden.
  4. Extension Method kann nur auf die öffentlichen Member/Methoden eines Typs zugreifen.

Trotz der schönen Anwendungsfälle die man sich da überlegen könnte (z.Bsp.: Implementierung eines Interfaces durch eine Extension-Method…) ist dazu angeraten dieses Feature nur Sparsam einzusetzen um Wildwuchs und schlecht wartbaren Code zu vermeiden.

Zum Schluss noch ein weiteres Beispiel mit Generics:

public static class Extensions
{
  public static T[] Slice<T>(this T[] source,
	int index, int count)
  {
    if (index < 0 || count < 0 ||
	source.Length - index < count)
            throw new ArgumentException();
    T[] result = new T[count];
    Array.Copy(source, index, result, 0, count);
    return result;
  }
}

...

int[] d = {0, 1, 2, 3, 4};
int[] a = d.Slice(4, 3); //entspr. Extensions.Slice(d, 4, 3)

…und noch eins zur Veranschaulichung einer Rahmenbedingung:

public static class E
{
 public static void F(this object obj, int i) { }
 public static void F(this object obj, string s) { }
}
class X { }
class Y
{
   public void F(int i) { }
}
class Z
{
   public void F(object obj) { }
}
class X
{
 static void Test(X x, Y y, Z z) {
   x.F(1);        // E.F(object, int)
   x.F("hello");  // E.F(object, string)
   y.F(1);        // Y.F(int)
   y.F("hello");  // E.F(object, string)
   z.F(1);        // Z.F(object)
   z.F("hello");  // Z.F(object)
 }
}

^ Teil 1: Übersicht aller Neuerungen (Einleitung)

< Teil 2: Implizit typisierte Variablen, Implizit typisierte Arrays

> Teil 4: Lambda Expressions

Advertisements

Kommentar verfassen

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden / Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden / Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden / Ändern )

Google+ Foto

Du kommentierst mit Deinem Google+-Konto. Abmelden / Ändern )

Verbinde mit %s

%d Bloggern gefällt das: