| 

.NET C# Java Javascript Exception

12
Hallo Code-Kickers,

wie steht Ihr zum Einsatz des C# Schlüsselwortes "var"?
Seit Ihr Gegner, Befürworter oder sogar Fans?

Ich persönlich konnte mich bisher noch nicht so sehr damit anfreunden.
Meiner Meinung nach leidet die Code-Lesbarkeit darunter.

Natürlich kann man seine Klassen und Methoden so nennen, dass sie auch trotz var lesbar und schlüssig sind. Es gibt z.B. Entwickler die vorhandenen Code strikt auf var umstellen (wird ja z.B. von Resharper so vorgeschlagen). Diese Methoden und Klassen sind in den meisten Fällen aber alles andere als gut benannt.

Ich sehe aber auch ein, dass Code-Umstellungen durch den Einsatz von "var" einfacher zu realisieren sind.

Wie ist Eure Meinung?

Gruß

CodeSniffer
News:
21.07.2011
CodeSniffer 1,3k 4 9
6
Ich bevorzuge es generell, den verwendeten Typ gleich sehen zu können. Das ist meist nicht schwieriger zu implementieren, dafür aber besser wartbar. Auch kann es sinnvoll sein, sich bewusst auf einen Datentyp zu einigen.
Hilfreich finde ich var allerdings oft bei den Ergebnissen von LINQ-Statements. Gerade hier kann es die Lesbarkeit erhöhen.
Fazit: Im großen und ganzen lehne ich var ab; aber bei nicht exzessiver Nutzung kann es in Einzelfällen hilfreich sein.
jsc 21.07.2011
Mir geht es genau so: ich verwende var aus Gründen der Lesbarkeit auch nicht.
KN 21.07.2011
7 Antworten
7
Wir haben da kürzlich relativ ausführlich darüber nachgedacht. Es gibt drei Fälle, in denen wir var zulassen:


  • Für anonyme Typen, denn da bleibt mir eh nichts anderes übrig. Wenn anonyme Typen in einem Projekt verwendet werden dürfen, dann muss dafür auch var zulässig sein.
  • Für Initialisierungen, bei denen nicht nur der Compiler den Typ herleiten kann, sondern auch der Leser des Codes. Das Beispiel von nabuchodonossor halt ich schon für grenzwertig, aber noch vertretbar, wenn bei derartigen Zuweisungen klar ist, dass var in diesem Fall dem explizit angegebenen generischen Typ SerializationAttribute entspricht. Ein weiteres Beispiel ist z.B.
    var map = new Dictionary<Guid, Tuple<Guid, List<string>>();

    denn das ist eindeuting nachvollziehbar, auch für den Leser des Codes. Da wir zu 95% Code nur lesen, ist Lesbarkeit ein zentrales Qualitätskriterium für Code.
  • Für Iterationen mit foreach.
    foreach(var item in list)


    Was ich für sehr gefährlich halte, ist eine Zuweisung an eine implizit mit var definierte Variable und ein Aufruf an diese mehrere/viele Zeilen später. Beispiel
    var item = GetItemFromSomewhere();
    // ...
    item.DoSomething();

    Solange die Methode GetItemFromSomewhere() einen Type liefert, der eine gültige DoSomething() Methode unterstützt, funktioniert dieser Code einwandfrei. Wenn GetItemFromSomewhere() einen solchen Typ aus irgendeinem Grund irgendwann nicht mehr liefert, habe ich aber den Fehler in der Zeile

    item.DoSomething();
    und nicht bei der Zuweisung

    var item = GetItemFromSomewhere();
    Der Zuweisungsfehler wird also verschleppt. Davor mag man auch in den von mir genannten Fällen nicht immer sicher sein, aber es ist eben unser Konsens aus Verständlichkeit und Effizienzgewinn.

    Kürzlich habe ich auf Eric Lippert's blog einen serh lesenswerten und ausführlichen Blogeintrag zu dem Thema gelesen (Uses and misuses of implicit typing), auch die Kommentare dazu regen sehr zum Nachdenken an. Es ist erstaunlich, welche Argumentationsketten für und wider des var-Schlüsselworts aufgebaut werden. Das muss jeder/jedes Team für sich selber wissen, vereinbaren und einhalten. Die Entscheidung für die drei von mir oben genannten Fälle wurden auch von Lippert's Blogbeitrag noch einmal beeinflusst, wie gesagt, das ist, was wir vereinbart haben.


EDIT:
Zum Thema Faulheit fällt mir noch was ein: Ich ertapp mich oft, dass ich eine Zeile Code mit var beginne, fertig schreibe und danach mit Refactor->Make Explicit das var per Tool beseitige.

Gruß
Florian
21.07.2011
ffordermaier 8,4k 3 9
Da sagst du was. Wie viele Stunden ich schon mit meinen Programmierern hier gesessen und über Pro und Contra philosophiert habe. Ergebniss lässt sich annähernd mit deinem vergleichen. Solange es klar ersichtlich ist, kein Problem. Sobald es unklar werden könnte wird explizit typisiert (auch wegen der von dir genannten Verschleppung).
Dustin Klein 21.07.2011
Das mit dem Verschleppen von Zuweisungsfehler finde ich auch besonders schlimm und kritisch. Auch deswegen setze ich var nicht gerne ein.
CodeSniffer 21.07.2011
Ich kenne Entwickler die aufgrund von Resharper-Hinweise alles auf var umstellen. Also genau umgekehrt ;-)
CodeSniffer 21.07.2011
Ganz ehrlich - ich hab den ReSharper auch mal ne Zeit lang ausprobiert und mir ist das zu viel und zu bunt. Und wenn der solche Vorschläge bringt, ...; ich hab DevExpress Refactor/CodeRush, diese Tools sind nicht so aufdringlich (ReSharper war mir zuviel Funktionalität in einem Tool, die immer irgendwie gleichzeitig zu laufen scheint).
ffordermaier 21.07.2011
Von ReSharper bin ich sehr überzeugt. Am Anfang erscheint es schon recht bunt. Gewöhnt man sich aber daran, möchte man es nicht mehr missen. Die Vorschläge und Farben kann man in den Optionen konfiguriern. So habe ich z.B. var abgeschaltet.
CodeSniffer 26.07.2011
3
Was wäre eine solche Diskussion ohne eine direkte Aussage von Microsoft? Also hier einmal einen Auschnitt zur Verwendung von var aus der MSDN:

Im folgenden Beispiel werden zwei Abfrageausdrücke veranschaulicht. Im ersten Ausdruck ist der Gebrauch von var zulässig, jedoch nicht erforderlich, da der Typ des Abfrageergebnisses explizit als IEnumerable<string> angegeben werden kann. Im zweiten Ausdruck hingegen muss var verwendet werden, da das Ergebnis eine Auflistung von anonymen Typen ist und der Name des Typs nur für den Compiler selbst zugänglich ist. Beachten Sie, dass in Beispiel 2 die foreach-Iterationsvariable item ebenfalls implizit typisiert sein muss.


// Example #1: var is optional because
// the select clause specifies a string
string[] words = { "apple", "strawberry", "grape", "peach", "banana" };
var wordQuery = from word in words
where word[0] == 'g'
select word;

// Because each element in the sequence is a string,
// not an anonymous type, var is optional here also.
foreach (string s in wordQuery)
{
Console.WriteLine(s);
}

// Example #2: var is required because
// the select clause specifies an anonymous type
var custQuery = from cust in customers
where cust.City == "Phoenix"
select new { cust.Name, cust.Phone };

// var must be used because each item
// in the sequence is an anonymous type
foreach (var item in custQuery)
{
Console.WriteLine("Name={0}, Phone={1}", item.Name, item.Phone);
}


Generell nutze ich teilweise auch ab und zu mal ein var, bin aber Fan der expliziten Typisierung wo es halt geht. Hier noch ein Link zur MSDN: Implizit typisierte lokale Variablen.
21.07.2011
Dustin Klein 2,9k 2 9
Zur Aussage von Microsoft: Ich habe es zwar nicht schriftlich, aber auf einer Schulung von Microsoft wurde dazu folgendes gesagt:

var wurde nur deshalb eingeführt, um die unbekannten Ergebnisse von Linq-Ausdrücken einer quasi typisierten Variablen zuweisen zu können. Für alle anderen Fälle wird von Microsoft empfohlen (Aussage des Lehrers), die vollständige Deklarationssystax zu verwenden.

Ich persönlich mag var nicht, denn ich will auf den ersten(!) Blick sehen, um welchen Typ es sich handelt. Und zuerst suche ich diesen immer links der Zuweisung.
Andreas Ganzer 21.07.2011
Ist auch meine persönliche Meinung. Wenn es klar ersichtlich ist *kann* man var benutzen, ich tendiere aber auch lieber zur expliziten Typisierung.
Dustin Klein 21.07.2011
2
Ich versuche es sooft als irgend Möglich zu verwenden - wenn man sich mal dran gewöhnt hat, ist das Argument mit der schlechteren Lesbarkeit auch wieder passé (wie mit allem). Mittlerweile empfinde ich unnötige Typangaben als störend. Ebenso stört mich, dass var nicht überall unterstützt wird (z.B. Member-Variablen mit Default-Wert).

Ich wiederhole mich nicht gerne (DRY-Prinzip). Das gilt auch für die Variablendeklaration.
Das ist nichts, was man mit Refactoring nicht auch hinbekommen würde (entsprechende Tools vorausgesetzt), aber wozu noch ein anderes Hilfmittel verwenden, wenn die Sprache es schon unterstützt.
Bei Änderungen am Rückgabewert einer (privaten) Funktion will ich nicht unbedingt jeden Aufruf überprüfen oder gar abändern (wenn ich weiß, dass der Typ mehr oder weniger "kompatibel" ist, wie z.B. zwischen float und double). Wenn strikt var verwendet wird, muss ich nur den Rückgabetyp anpassen, den Rest decken die Tests ab, die ja sowieso in allen Projekten in Übermaß vorhanden sind *g* - sind wir nicht alle Musterschüler.

Aus gleichem Grund versuche ich - soweit Möglich - auf die Angabe des Typs bei generischen Membern zu verzichten (wenn der Typ sich aus den übergebenen Werten erschließen lässt). Z.B. bei Linq
var numbers = new[] { 3, 1, 2 };
var orderedNumbers = numbers.OrderBy( number => number );
var firstNumber = orderedNumbers.First( );
statt
int[] numbers = new int[] { 3, 1, 2 };
IOrderedEnumerable<int> orderedNumbers = numbers.OrderBy<int, int>( ( int number ) => number );
int firstNumber = orderedNumbers.First<int>( );

Das Beispiel ist zwar unnötig, stell das aber mal ohne zu Fluchen auf einen anderen Typ (z.B. decimal) um ;)
var numbers = new[] { 3m, 1m, 2m };
var orderedNumbers = numbers.OrderBy( number => number );
var firstNumber = orderedNumbers.First( );
statt
decimal[] numbers = new decimal[] { 3m, 1m, 2m };
IOrderedEnumerable<decimal> orderedNumbers = numbers.OrderBy<decimal, decimal>( ( decimal number ) => number );
decimal firstNumber = orderedNumbers.First<decimal>( );
21.07.2011
WolfgangKluge 1,0k 2 7
"den Rest decken die Tests ab, die ja sowieso in allen Projekten in Übermaß vorhanden sind *g* - sind wir nicht alle Musterschüler" - Allein dafür bekommst du schon ein +1 von mir ;-)
Dustin Klein 21.07.2011
Das Argument mit der Fehlerverschleppung ist natürlich contra var ;)
WolfgangKluge 21.07.2011
Ich sehe - gerade bei numerischen Datentypen - das Problem, das man sich da ganz schnell ins Bein schießen kann. Während ein Vergleich (i == j) für int i,j wohldefiniert ist, gerätst du für double i,j in Schwierigkeiten (Thema: Genauigkeit der Gleitkommadarstellung). Mit einem var übersieht man das meiner Meinung nach leichter.
ffordermaier 21.07.2011
Das stimmt natürlich ebenfalls (und sollte im Idealfall durch Tests ans Tageslicht kommen - darauf zu hoffen ist auch nicht der richtige Ansatz).

Allerdings gilt das auch für die manuelle nachbearbeitung und bei der Refactoring-Variante. Ganz das Hirn abschalten darf man wohl nie ;)
WolfgangKluge 21.07.2011
2
Guck Dir mal Alles var - oder nicht? an ...
26.07.2011
Golo Roden 2,7k 3 9
Danke, sehr guter Beitrag. Das deckt sich auch größtenteils mit meinen Vorstellungen.
CodeSniffer 27.07.2011
Danke schön :-)!
Golo Roden 27.07.2011
2
@Golo: falls Du hier mal wieder reinschauen solltest, könntest Du vielleicht den Link reparieren? Der scheint inzwischen ins Leere zu führen.
Matthias Hlawatsch 15.04.2012
1
Nicht nur der Link. Im ganzen Blog steht mittlerweile leider quasi nichts mehr - was ich persönlich sehr schade finde denn dort waren doch ein paar informative Artikel.
Jens Duczmal 15.04.2012
1
var erspart unter gewissen Umständen immensen Tippaufwand:

var memberAttr = reflectionProvider.GetSingleAttributeOrDefault<SerializationAttribute>(memberInfo);
21.07.2011
nabuchodonossor 1,3k 5
Also aus Faulheit? ;-)
Wenn aber die Code-Leserlichkeit darunter leidet?
CodeSniffer 21.07.2011
1
Jein: Wenn ich memberAttr verwende, sehe ich - dank Intellisense - auch welcher Typ er ist. Und in der Deklaration habe ich den Datentyp ja ohnehin auch stehen. Ich denke nicht, dass die Codeleserlichkeit ernsthaft gefährdet ist.
nabuchodonossor 21.07.2011
Und - je weniger ich schreiben muss, umso früher wird geliefert und Kunde bezahlt. Aufgrund der Schnelllebigkeit unserer Branche mache ich mir um die Evolvierbarkeit des Codes keine Gedanken mehr. Bis der Kunde wieder bestellt, ist mindestens eine Technikgeneration weitergegangen, und man muss meist eh alles wieder schmeissen.
nabuchodonossor 21.07.2011
1
Kommt natürlich auch darauf an wieviele Leute gemeinsam am Code arbeiten. Bei einem größeren Team erleichtert eine genaue Deklaration die Lesbarkeit schon enorm.
CodeSniffer 21.07.2011
1
Ich möchte es direkt ohne Intellisense den Typ sehen, daher verwende ich var immer wenn ich den Typ direkt auf der rechten Seite vom = sehe:

var p1 = new Point2d(); // OK für mich
var p2 = GetPoint(); // nicht OK für micht, da ich den Typ nicht direkt sehe
Point3d p3 = GetPoint(); // daher so, denn jetzt sehe ich den Typ direkt

Kurze Nachtrag. Bei LINQ ist es auf Grund der anonymen Datentypen recht nett. Dennoch versuche ich auch dort wenn es einen expliziten Typ gibt diesen zu nutzen, damit man direkt sieht was aus dem Query kommt
21.07.2011
KCT 937 1 8
KCT 937 1 8
Im 2. Fall lässt sich der Typ aus der Methode ableiten.
Ein Problem mit var hat man IMO nur, wenn die Bezeichner schlecht benannt sind.
Jürgen Gutsch 19.07.2012
0
Hier stand Unsinn, sorry. Danke ffordermaier!
21.07.2011
Xantiva 2,3k 2 9
Xantiva 2,3k 2 9
2
Kann es sein, dass du var mit dynamic verwechselst?
ffordermaier 21.07.2011
Ähm, <rotwerd> zu großen Teilen schon.
Xantiva 21.07.2011

Stelle deine .net-Frage jetzt!