I’ve noticed a worrying trend of late, when looking at code written by developers who are new to C#, or have never worked with the language prior to C# 3.0. I am referring to the misuse and overuse of the var keyword.
The purpose of var, for those who don’t know, is to omit the type name when declaring a local variable in situations where the type name is unknown, unavailable or doesn’t exist at the point where the code is written. The primary case where this is true is for anonymous types, whose type name is provided at compile-time. It is also used in LINQ where the result of a query cannot easily be inferred by the programmer, perhaps because it uses grouping structures, nested generic types or, indeed, anonymous types as well.
There seems to be a tendency for some programmers to use var for every variable declaration. Sure, the language doesn’t stop you from doing this and, indeed, MSDN admits that this is a “syntactic convenience”… But it also warns quite strongly that:
…the use of var does have at least the potential to make your code more difficult to understand for other developers. For that reason, the C# documentation generally uses var only when it is required.
Implicitly Typed Local Variables (C# Programming Guide), MSDN
I discovered recently that the commonly-used tool ReSharper practically mandates liberal use of var. Frankly, this isn’t helping the situation. There are some developers who try to argue the stance that var somehow improves readability and broader coding practices, such as this article:
By using var, you are forcing yourself to think more about how you name methods and variables, instead of relying on the type system to improve readability, something that is more an implementation detail…
var improves readability, Hadi Hariri
I agree with the premise of the quote above, but not with the end result. On the contrary, the overuse and misuse of var can lead to some very bad habits…
Let’s look at the argument against the widespread use of var (and for its sparing, correct use):
Implicitly-typed variables lose descriptiveness
The type name provides an extra layer of description in a local variable declaration:
// let's say we have a static method called GetContacts() // that returns System.Data.DataTable var individuals = GetContacts(ContactTypes.Individuals); // how is it clear to the reader that I can do this? return individuals.Compute("MAX(Age)", String.Empty);
My variable name above is perfectly descriptive; it differentiates between any other variables populated using GetContacts() and indeed other variables of type DataTable. When I operate on the variable, I know that it’s the individual contacts that i’m referring to, and that anything I derive from them will be of that context. However, without specifying the type name in the declaration, I lose the descriptiveness it provides…
// a more descriptive declaration DataTable individuals = GetContacts(ContactTypes.Individuals)
When I come to revisit this body of code, i’ll know not only what the variable represents conceptually, but also its representation in terms of structure and usage; something lacking from the previous example.
‘var’ encourages Hungarian Notation
If the ommission of type names from variable declarations forces us to more carefully name our variables, it follows that variable names are more likely to describe not only their purpose, but also their type:
var dtIndividuals = GetContacts(ContactTypes.Individuals);
This is precisely the definition of Hungarian Notation, which is now heavily frowned upon as a practice, especially in type-safe languages like C#.
Specificity vs. Context
There’s no doubt that variable names must be specific, however, they need never be universally-specific. Just as a local variable in one method doesn’t need to differentiate itself from variables in other methods, a declaration that includes one explicit type need not differentiate itself from variables of a different explicit type. Implicit typing with var destroys the layer of context that type names provide, thus it forces variable names to be specific regardless of type:
// type provides context where names could be perceived as peers Color orange = canvas.Background; Fruit lemon = basket.GetRandom(); //... // this is far less obvious var orange = canvas.Background; var lemon = basket.GetRandom(); // you can't blame the programmer for making this mistake SomeMethodThatOperatesOnFruit(orange);
Increased reliance on IntelliSense
If the type name is now absent from the declaration, and variable names are (quite rightly) unhelpful in ascertaining their type, the programmer is forced to rely on IDE features such as IntelliSense in order to determine what the type is and what methods/properties are available.
Now, don’t get me wrong, I love IntelliSense; I think it’s one of the most productivity-enhancing features an IDE can provide. It reduces typing, almost eliminates the need to keep a language reference on-hand, cuts out many errors that come from false assumptions about semantics… the list just goes on.
Unfortunately, the ultimate caveat is that IntelliSense isn’t universally available; you can write C# code without it, and in some cases I think that programmers should! Code should be easily-maintainable and debuggable in all potential coding environments, even when IntelliSense is unavailable; and implicitly-typed variables seriously hinder this objective.
No backwards compatibility
One of the advantages of an object-oriented language like C# is the potential for code re-use. You can write a component and use it in one environment (e.g. WPF, .NET 3.5), then apply it in another (e.g. ASP.NET 2.0). When authoring such components, it’s useful to be aware of the advantage of that code working across as many versions of the language and framework as possible (without impeding functionality or adding significant extra code, of course).
The practice of using var for all local variable declarations renders that code incompatible with C# 2.0 and below. If var is restricted to its intended use (i.e. LINQ, anonymous types) then only components which utilise those language features will be affected. I’ve no doubt that a lot of perfectly-operable code is being written today that will be useless in environments where an older version of the framework/language is in use. And believe me, taking type names out of code is a hell of a lot easier than putting type names back in to code.
I sincerely hope that people will come away from this article with a better understanding of the purpose of the var keyword in C#, when to use it and, more importantly, when not to use it. As a community of developers, it’s important to encourage good practices and identify questionable ones; and I believe that the overuse of var is certainly one such questionable practice.