Am 13. Oktober 2008 haben Peter Bucher und ich unter dem Titel Noch Fragen, Bucher? Ja, Roden! angekündigt, jeweils zum ersten eines jeden Monats einen Kommentar zu einem vorab gemeinsam gewählten Thema verfassen zu wollen. Bisher sind in dieser Reihe folgende Kommentare erschienen:
Heute, am 1. September 2009, ist es nun wieder so weit, und unser Thema für diesen Monat lautet:
Alles var – oder nicht?
So wohl Peter wie auch ich haben uns unabhängig voneinander im Vorfeld unsere Gedanken gemacht, wie wir diesem Thema gegenüberstehen. Peters Kommentar findet sich zeitgleich in seinem Blog, folgend nun mein Kommentar zu diesem Thema:
Im Grunde lassen sich die Neuerungen in C# 3.0 auf einen einzigen Aspekt reduzieren: LINQ. Alle Änderungen und Erweiterungen, die C# außer LINQ erfahren hat, sind durch LINQ begründet. Anders formuliert: Wäre LINQ nicht eingeführt worden, wäre kein Bedarf für die anderen Features von C# 3.0 gegeben gewesen.
Obwohl dies nicht der ursprünglichen Intention entspricht, lassen sich diese anderen Features jedoch auch ohne LINQ nutzen:
- Lambdaausdrücke sind eine kompakte und komfortable Möglichkeit, anonyme Methoden und Eventhandler zu implementieren.
- Erweiterungsmethoden eignen sich wunderbar, um Methoden für generische Zwecke wie beispielsweise Konvertierung auf elegante Weise an bestehenden Datentypen zur Verfügung zu stellen.
- Automatisch implementierte Eigenschaften und Objekt- wie auch Listeninitialisierer ersparen dem Entwickler einiges an unnötiger Tipparbeit.
Das einzige Feature, das ohne LINQ nur selten genutzt wird, sind anonyme Typen. Allerdings wird das zugehörige Schlüsselwort var umso häufiger auch abseits von LINQ genutzt. Daraus ergibt sich relativ schnell die Frage, wann var eigentlich genutzt werden sollte und wann nicht: Was sind die Best Practices für den Einsatz von var?
Zunächst einmal bleibt festzuhalten, dass die Verwendung von var nichts an der starken Typisierung von C# ändert: Anders als beispielsweise der weit verbreitete untypisierte Datentyp Variant entbindet das Schlüsselwort var nicht von der starken Typisierung – im Gegenteil, die Typisierung findet ebenso stark statt wie zuvor, nur eben implizit statt explizit.
Was var intern nämlich macht, ist, den Typ des Ausdrucks auf der rechten Seite einer Zuweisung auszuwerten, und diesen Typ für die Variablen auf der linken Seite der Zuweisung zu verwenden. Diese Technik wird – da der Typ hergeleitet wird – auch als Type Inferring bezeichnet.
Prinzipiell kann man also nichts grundlegend falsch machen, wenn man alle explizit angegebenen Typen durch das Schlüsselwort var ersetzen würde. Trotzdem empfiehlt es sich nicht immer: Auf var sollte nämlich dann verzichtet werden, wenn die Lesbarkeit leiden würde, und es nicht mehr auf den ersten Blick offensichtlich wäre, um welchen Typ es sich handelt.
Während beispielsweise die Zuweisung eines generischen Datentyps
var dictionary = new Dictionary<string, int>();
auch ohne explizite Angabe des zu verwendenden Typs problemlos lesbar ist, sieht dies bei den eingebauten Datentypen bereits ganz anders aus:
var number = 2147483746;
Es liegt auf der Hand, dass bei einigen Werten nicht mehr auf den ersten Blick eindeutig zugeordnet werden kann,um welchen Datentyp es sich handelt. Anfällig sind dabei vor allem die folgenden Kombinationen:
- int oder long?
- float oder double?
Zieht man außerdem auch noch die nicht-vorzeichenbehafteten Datentypen – wie beispielsweise short oder ulong – hinzu, wird das Chaos perfekt.
Für eingebaute Datentypen sollte das Schlüsselwort var also offensichtlich möglichst nicht verwendet werden. Dies ist der eine Extremfall. Der andere Extremfall sind die anonymen Typen, deren Verwendung ohne das Schlüsselwort var gar nicht erst möglich ist.
Doch wie sieht es zwischen diesen beiden Extremen aus?
Ein Beispiel wurde bereits genannt: Die Lesbarkeit von generischen Datentypen kann durch die Verwendung des Schlüsselwortes var durchaus verbessert werden, immerhin wird durch var an dieser Stelle Redundanz vermieden. Diese Feststellung kann man dabei durchaus zur Regel erheben:
Das Schlüsselwort var kann immer dann guten Gewissens angewendet werden, wenn es redundante Typangaben verhindert – sofern mindestens ein Vorkommen des Typs nach wie vor bestehen bleibt.
Mit dieser Regel hat man bereits die meisten Anwendungsfälle abgedeckt, ansonsten sollte man von var Abstand nehmen.
Eine Ausnahme gibt es jedoch noch: Innerhalb von Schleifen – und hierzu zählen insbesondere auch die foreach-Schleifen – kann für die Definition der Schleifenvariable in der Regel das Schlüsselwort var verwendet werden, sofern auch dann noch auf den ersten Blick ersichtlich ist, von welchem Typ die Schleifenvariable ist.
Zusammengefasst lässt sich also sagen, dass man auf den Einsatz von var zu Gunsten einer besseren Lesbarkeit verzichten sollte – es sei denn, redundante Typangaben werden vermieden. Für Schleifenvariablen kann var verwendet werden, sofern der zugehörige Typ nach wie vor auf einen Blick ersichtlich ist.