Erweiterungsmethoden in C# 👍 👎

Die meisten haben sicherlich bereits von den sog. Erweiterungsmethoden unter C# gehört, meinem Eindruck nach haben jedoch deutlich weniger eine konkrete Vorstellung davon oder sie gar bereits selbst verwendet. Dies ist jedoch ganz einfach und kann durchaus nützlich sein, weshalb ich hier eine kleine Einführung geben möchte.

Ganz allgemein lässt sich sagen, dass Typen (sowohl eingebaute, als auch selbst definierte) mittels Erweiterungsmethoden um neue Operationen ergänzt werden können – im Ergebnis also ähnlich zur herkömmlichen Ableitung von einer Klasse, doch dazu später noch ein paar Worte mehr.

Wir möchten in diesem Beitrag den DateTime-Typen insofern erweitern, dass er die komfortable Konvertierung eines DateTime-Objekts zu einem UNIX-Zeitstempel ermöglicht, was insbesondere sinnvoll sein kann, wenn alte (z. B. PHP-basierte) Projekte mit entsprechenden Werten in einer Datenbank auf ASP.NET umgestellt werden sollen.

Um dieses Verhalten zu implementieren ist nicht mehr nötig, als in einer statischen Klasse eine öffentliche statische Methode der gewünschten Funktionalität zu implementieren, welche jedoch einen speziellen ersten Parameter erhält:
Erweiterungsmethode für "DateTime" implementieren
01020304050607
public static class ExtensionMethods {    public static int ToUnixTimestamp(this DateTime dateTime) {        DateTime unixBaseTime = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
return Convert.ToInt32((dateTime.ToUniversalTime() – unixBaseTime).TotalSeconds); }}
Bei dem bereits angekündigten "speziellen ersten Parameter" handelt es sich also um "this DateTime", wobei das Schlüsselwort this der Hinweis dafür ist, dass der nachfolgende Typ (in diesem Fall DateTime) erweitert werden soll.

Die Verwendung ist anschließend denkbar einfach, da sich derartige Operationen aus Sicht des Entwicklers im weiteren Verlauf wie Instanzmethoden des entsprechenden Objekts verhalten:
Erweiterungsmethode für "DateTime" verwenden
010203040506
  // Zeitstempel für "jetzt"int unixTimestamp = DateTime.Now.ToUnixTimestamp();
// Zeitstempel für beliebiges DateTime-ObjektDateTime birthdate = new DateTime(1988, 1, 29);int unixTimestamp = birthdate.ToUnixTimestamp();
Der erste Parameter (also der mit this) wird dabei übrigens nicht mit angegeben, da er implizit durch die Instanz gegeben ist. Es gilt außerdem noch zu beachten, dass ggf. der Namensraum eurer Erweiterungsmethoden eingebunden werden muss, sofern er von dem des "Einsatzortes" abweicht.

Nun gilt natürlich noch zu klären (s. o.), wie sich dieses Vorgehen zur "normalen" Ableitung verhält. Dies ist tatsächlich gar nicht immer absolut festzumachen, was man im konkreten Fall einsetzen sollte, aus Sicht eines objektorientierten Designs sollte üblicherweise jedoch Vererbung bevorzugt werden, zumal Erweiterungsmethoden nur auf öffentliche Mitglieder zugreifen können und bei Namenskonflikten ggf. das Nachsehen haben. Es gibt jedoch Fälle, wo dies nicht möglich ist: So ist beispielsweise der eingebaute Typ string als sealed markiert, so dass davon nicht geerbt werden kann. In einem solchen Fall kann die Ergänzung per Erweiterungsmethode sinnvoll sein. Auch in unserem Beispiel halte ich den Einsatz von Erweiterungsmethoden für legitim, schon weil ein neuer Typ (etwa "DateTimeWithUnixTimestampCapability"? Smiley: winking) nur begrenzt sinnvoll erscheint.

Möglicherweise benutzt ihr im Übrigen sogar ständig Erweiterungsmethoden, ohne es zu wissen. Microsoft macht davon nahezu exzessiven Gebrauch im Zusammenhang mit LINQ, um euch so komfortable Operationen wie Count(…) und Where(…) auf beliebigen Objekten anbieten zu können, die IEnumerable implementieren.


Projektverweise

Kategorien / Archiv  |  Übersicht RSS-Feed

Schlagworte

Suche