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:
- Die Klasse in der eine Extension-Method erstellt wird, muss static sein. Das gleiche gild für die Extension-Method selber.
- 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.
- Instanz-Methoden haben immer vor Extension-Methods Vorrang. Es kann also keine vorhanden Funktion durch eine Extension-Method ersetzt werden.
- 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

