Seit C# 3.0 können DotNets eingebaute native ValueTypes wie int, string und double um neue Methoden erweitert werden, ohne die Definition der zugrundeliegenden Klassen ändern zu müssen. Diese sogenannten Extension-Methoden können so aufgerufen werden, als währen sie Member-Methoden der Klasse. Ähnliche Konzepte sind mir mal bei Ruby über den Weg gelaufen. Natürlich kann dieses Verfahren auch auf eigene Typen angewandt werden. Extension Methods sind nicht auf eingebaute Typen beschränkt.
Beispiel:
Wir wollen den eingebauten Typ “Integer” um eine Methode “sqr” erweitern, die das Quadrat des Wertes ermittelt und zurück gibt. Die Notwendigkeit dieses Beispiels sei einfach mal dahin gestellt. Es ist lediglich ein Beispiel:
public static class IntErweiterung { public static int sqr(this int i) { return i * i; } } |
Mit dieser statischen Klasse wird folgendes möglich:
Console.WriteLine(20.sqr()); // 400 |
int x = 5; int y = x.sqr(); Console.WriteLine(y); // 25 |
Hier stellt sich mir die Frage, warum es dann das Schlüsselwort sealed gibt, mit dem man eine Klasse versiegeln kann, um zu verhindern, das sie überschrieben wird. Vermutlich liegt der Unterschied zwischen der Verberung von Klassen und der Erweiterung via Extension Methods darin, das Extension Methods nur auf öffentliche Member zugreifen können. Damit wäre dann der Sinn einer versiegelten Klasse auch wieder hergestellt.
Probieren wir es einfach mal aus:
public class test { int m_i; public test(int i) { m_i = i; } } public static class testExtension { public static int getI(this test i) { return i.m_i; } } |
Wir versuchen hier, die Klasse test um die fehlende öffentliche Methode “getI” zu erweitern, die den privaten Member “m_i” zurück geben soll.
Der Compiler sagt: “Der Zugriff auf “linqtest.test.m_i” ist aufgrund der Sicherheitsebene nicht möglich.”
Na dann ist die Weltordnung wieder hergestellt. Extension Methods können die Architektur einer Software zumindest dann ein wenig vereinfachen, wenn ein Wrapper oder ein Adapter geschrieben werden müsste, um eine bestehende nicht-vererbbare Klasse um neue Methoden zu erweitern.
Die Privacy bzw. die Integriät einer Klasse bleibt also gewährleistet. Extension Methods können nur auf öffentliche Member zugreifen und können u.a. dazu benötigt werden, DesignPatterns wie Adapter wieder aufzulösen (wenn man dies denn möchte).
Eine der großartigen Neuerungen im Sprachumfang von C# bzw. .NET 3.5 sind Lambda und LINQ.
Lambda erinnert mich einerseits an DEFINES von Ansi C, und andererseits an die sog. “Functors” von C++ und wurden hier vermutlich auch abgeguckt. Dennoch wurde Lambda integrativer gelöst, da ein Lambda-Ausdruck direkt innerhalb des Codes erfolgen kann, wo er benötigt wird. C++ – Functors wurden bzw werden i.d.R. als separate Klassenrümpfe mit einem überladenen operator() definiert.
Ein Lamda-Ausdruck sieht zum Beispiel so aus:
Func<int , int> sqr = x => x * x; Console.WriteLine(sqr(10)); // Result: 100 </int> |
LINQ (Abkürzung für Language INtegrated Query) ist eine Komponente von Microsofts .NET-Framework, mit der SQL-, XLink- und XQuery-Anfragen direkt in .NET-Programmiersprachen wie C# 3.0 oder VB.Net 9.0 als Code statt als String eingebunden werden können. LINQ wurde federführend von Turbo-Pascal- und C#-Autor Anders Hejlsberg entwickelt.
LINQ erweitert C# u.a. um direkte Selektion von Datenmengen innerhalb des Codes. Es wird keine Query in String-Form abgesetzt, sondern unmittelbar in dem Code integriert.
Am besten erklärt sich LINQ ein einem kleinen, konkreten Beispiel:
string[] names = { "Faust", "Peter", "Tom", "Fred", "August" }; var foundNamesAsQuery = from s in names where s[0] == 'F' select s; foreach (string name in foundNamesAsQuery) Console.WriteLine(name); // Result: Faust, Fred |
Wenn LINQ schon in einer SQL-Syntax Datenmengen selektieren und filtern kann, unterstützt es dann auch Sortierungen à la “ORDER BY”? Mal gucken:
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace linqtest { class Program { static void Main(string[] args) { string[] names = { "Faust", "Peter", "Tom", "Fred", "August" }; var foundNamesAsQuery = from s in names where s[0] == 'F' orderby s descending select s; foreach (string name in foundNamesAsQuery) Console.WriteLine(name); Console.ReadLine(); } } } |
Nach Jahren aktiv gelebter Windows-Ignoranz habe ich mich in den letzten Wochen wieder verstärkt mit Microsofts Windows .NET beschäftigt. Re-Angefixt wurde ich vor allem durch Mono 2.0 , der platformunabhängigen Implementierung von GNOME-Mitbegründer Miguel de Icaza, welche vor kurzem veröffentlicht wurde.
Ich muss ganz ehrlich zugeben, das ich ziemlich erstaunt war über die Weiterentwicklung von .NET. Zu “meiner Zeit” schrieb man die Version 1.1. bzw 2.0. Inzwischen sind die Jungs bei 3.5 angekommen. Man möge mich jetzt steinigen (Anm.d.Red.:ich werde auch vorläufig nicht mein Linux von der Notebook-Platte putzen),
Continue reading…