Jede in den vergangenen sieben Jahren erschienene Version von C# konzentrierte sich auf einen speziellen Bereich:
- C# 1.0 war auf Objektorientierung ausgelegt und bildete das äußerst konsistente objektorientierte Modell von .NET auf die eigentliche Sprache ab.
- C# 2.0 enthielt als wesentliche Neuerung generische Typen. Alle weiteren Features waren letztlich nur für die konsistente Umsetzung dieses Themas erforderlich.
- C# 3.0 verfügte mit LINQ über die Möglichkeit, nahezu beliebige Datenquellen in einer ausgesprochen effizienten Art auf deklarative Weise abzufragen.
Das besondere an all diesen Versionen von C# war, dass eine bemerkenswerte Konsistenz gegeben war – nicht nur innerhalb der einzelnen Versionen, sondern auch versionsübergreifend.
Auf der PDC 2008 hat Microsoft im Oktober des vergangenen Jahres die kommenden Neuerungen von C# 4.0 vorgestellt. Auch diese Version wird wieder von einem Thema geprägt sein: Der Integration von C# mit dynamischen Sprachen und COM.
Anders als in den vergangenen Versionen fallen die Änderungen dieses Mal allerdings verhältnismäßig kompakt aus, Angekündigt sind derzeit sogar nur vier Features, wobei sich daran bis zur finalen Version von C# 4.0 voraussichtlich auch nichts mehr ändern wird:
- dynamic-Schlüsselwort: Das Schlüsselwort dynamic erlaubt die Instanziierung von dynamischen Typen, deren Typ erst während der Ausführung festgelegt wird – und der sich sogar ändern beliebig kann. Intern basiert dynamic auf object, erweitert dieses aber um Late Binding.
- Optionale Parameter: Optionale Parameter ermöglichen es, einzelne Parameter einer Methode bei deren Aufruf auslassen zu können, und statt dessen auf Standardwerte zurückzugreifen. Letztlich erspart sich der Entwickler die Erzeugung verschiedener überladener Varianten einer Methode.
- Benannte Parameter: Benannte Parameter dienen dazu, einzelne Parameter einer Methode bei deren Aufruf gezielt, das heißt, unabhängig von ihrer Position in der Parameterliste spezifizieren zu können. Dieses Feature ergibt insbesondere in der Kombination mit optionalen Parametern Sinn.
- Ko- und Kontravarianz: Durch eine verbesserte Ko- und Kontravarianz werden die Möglichkeiten zur Spezialisierung beziehungsweise Generalisierung verbessert. So kann beispielsweise nun List<string> als Ersatz für List<object> verwendet werden, da string von object ableitet – obwohl dies für List<string> und List<object> nicht gilt.
Man mag es bedauerlich finden, dass C# 4.0 nur diese wenigen Änderungen enthält. Potenzial für weitere Aspekte wäre durchaus vorhanden gewesen. Andererseits spricht es für die Reife einer Sprache, wenn eine gewisse Sprachstabilität erreicht wurde und nicht jede neue Version eine Unmenge an weiteren Features enthält.
Wie bereits bei den meisten Neuerungen von C# 3.0 bemüht sich Microsoft auch bei C# 4.0, darauf hinzuweisen, dass dessen Neuerungen nicht für den tagtäglichen Gebrauch gedacht sind, sondern explizit nur der vereinfachten Interoperabilität zu dynamischen Sprachen und vor allem COM dienen.
Bei dem Schlüsselwort dynamic mag dies ohne weitere Erklärung einleuchten, doch wie steht es um die anderen Features?
Ko- und Kontravarianz sind mit Sicherheit nicht nur das am wenigsten beachtete, sondern auch am wenigsten verstandene Merkmal – zugleich jedoch auch das leistungsfähigste. Schließlich ermöglichen diese beiden Aspekte eine deutlich bessere Verwendung von Schnittstellen und implementierenden, aber spezialisierenden Klassen.
Da für die Verwendung dieser erweiterten Ko- und Kontravarianz jedoch auch zwei neue Schlüsselwörter erforderlich sind, ist fraglich, ob sich die Verwendung dieses Feature all zu weit verbreiten wird. Dies wäre schade, allerdings auch nicht tragisch.
Kritisch sind jedoch die beiden übrigen Features: Optionale und benannte Parameter. Das Problem mit diesen ist, dass man zu schnell glaubt, diese verstanden zu haben, ohne es jedoch wirklich getan zu haben. Das Problem liegt in der Implementierung der Standardwerte von optionalen Parametern.
Prinzipiell ist es möglich, optionale Parameter als syntaktisch kompakten Ersatz für die Erzeugung verschiedener überladener Methoden zu verwenden. Für den Aufrufer macht dies keinen Unterschied: Er kann so oder so eine Methode mit weniger Parametern aufrufen, als es für den Aufruf der primären Methode erforderlich wäre.
Allerdings stellt sich die Frage, wie die Standardwerte der fehlenden optionalen Parameter ermittelt werden. Bei einer klassischen Überladung ist die Antwort offensichtlich: Hier stecken die Standardwerte in den überladenen Methoden. Wird ein Standardwert in einer dieser Methoden geändert, wirkt sich das automatisch auf alle Verwender aus – selbst wenn diese sich in einer anderen Assembly befinden, die nicht neu kompiliert wird.
Anders sieht dies jedoch bei der Verwendung optionaler Parameter aus, wie Bernd Marquardt, Neno Loje und ich herausgefunden haben: Hierbei werden die jeweiligen Standardwerte beim Kompilieren in den Code des Verwenders (!) kopiert. Das heißt, dass sich eine Änderung eines Standardwertes eines optionalen Parameters nur dann auf den Verwender durchschlägt, wenn auch dieser neu kompiliert wird.
Sofern sich der Verwender in der gleichen Assembly wie die aufzurufende Methode befindet, geschieht dies auch automatisch. Ist dies jedoch nicht der Fall, wird die betroffene Methode zukünftig mit potenziell falschen oder sogar ungültigen Parametern aufgerufen.
Kritisch hieran ist, dass man einem Methodenaufruf nicht ansieht, ob intern eine überladene Methode oder eine Methode mit optionalen Parametern aufgerufen wird. Es handelt sich also um eine Verletzung des Uniformitätsgesetzes der Informatik, das besagt, dass semantisch verschiedene Dinge auch über eine verschiedene Syntax verfügen sollten.
Was folgt nun aus all diesem? Optionale Parameter sind – wie von Microsoft auch vollkommen korrekt erwähnt – nicht für den tagtäglichen Gebrauch gedacht. Statt dessen sollten sie nur dann Verwendung finden, um eine vereinfachte Interoperabilität zu Legacycode herzustellen – wie beispielsweise im Falle von COM. Man denke nur an die zahlreichen Type.Missing-Angaben bei zahlreichen Aufrufen in das API von Office.
Allerdings werden viele Entwickler optionale Parameter als komfortable Alternative zu überladenen Methoden sehen. Und genau dafür sind optionale Parameter eben nicht gedacht.
Sofern man also weder mit dynamischen Sprachen noch mit COM hantiert, bleibt als einzige relevante Neuerung von C# 4.0 schließlich die Verbesserung von Ko- und Kontravarianz.