This article contains my personal opinions about how the C# var keyword should and should not be used. It probably won’t persuade anyone to change how she or he will writes code. Of course, everyone should be following the coding standards followed by their team. I just wanted to voice all my thoughts on this keyword. There are many other articles on the Internet on the use of the C# var keyword but I am trying to identify other thoughts that may have been missed. It was released with C# 3.0 and .NET 3.5.
I also passed the idea of using the C# var keyword to some of the Intertech consultants and I received valuable feedback from them. Thanks, folks!
I personally don’t think I’ll ever understand why so many C# developers prefer (even recommend) almost always declaring local variables as “var” instead of defining the actual data types. Even .NET “best practices” books and programming tools such as JetBrains Resharper recommend using “var” by default. No – I’ll never fully understand the advantages of using this vague data type definition.
When do I like using C# var? I fully agree that “var” can and should be used with LINQ queries that return custom collections. It can be used for defining the variable that holds the result of the query. It can also be used within a “foreach” loop as an iterator for cycling through the results, like this:
static void Main() { List<string> myCars = new List<string>() { "Mercury Cougar", "Dodge Dart", "Ford Taurus SHO", "Dodge Charger", "Chevrolet Blazer", "Dodge Neon" }; var dodges = from someCars in myCars where someCars.Contains("Dodge") orderby someCars descending select someCars; foreach (var car in dodges) { Console.WriteLine(car); } Console.WriteLine("\nThe collection type is: \n{0}", dodges.GetType()); Console.ReadKey(); }
It gives us the following results, with an interesting custom collection that just begs for “var” to be used:
This makes sense! This is one of the primary reasons “var” was created.
This keyword is also used when we create anonymous objects.
var myFastCar = new { Color = "Yellow", Year = "2007", Make = "Dodge", Model = "Charger SRT" }; // Returns: // { Color = Yellow, Year = 2007, Make = Dodge, Model = Charger SRT } Console.WriteLine(myFastCar);
As well, I see nothing wrong with using “var” with a local variable declaration in a method, particularly if I’m initializing it with a call to a class’s constructor, like so:
// Oy - this is too much typing! ReallyFastCarWithRidiculouslyLongClassName myCar1 = new ReallyFastCarWithRidiculouslyLongClassName(); // Better! var myCar2 = new ReallyFastCarWithRidiculouslyLongClassName();
Heck – this is great! It is ridiculous having to type the class name twice when creating an object, although the second reference is actually a call to the constructor. If you consider using “var” this way, it’s very much the same way VB creates new object instances.
' VB code Dim myCar1 As New ReallyFastCarWithRidiculouslyLongClassName()
Okay – when do I think it can cause trouble? For one example, when you are calling a factory method that returns an instance of another object. When it comes to code development and more important code maintenance, you cannot simply scan the code with your eyes to truly understand what objects you are working with. You must hover over each method with your mouse to see what type is being returned.
Some of the consultants I Yammered with here at Intertech about “var” mentioned that without it, the fully-defined return types appear as clutter (noise), unnecessarily complicating the code. That makes sense. They also mentioned that if the type returned is only going to be used in one additional instruction, knowing its exact type becomes less important. I see their points.
I also got feedback from a developer who doesn’t like to use “var” but instead will declare an interface variable whenever possible, programming to its implementation. This works great so long as you don’t need to use the standard non-interface members.
In addition, I also received feedback from developers with heavy Python or JavaScript backgrounds that it just felt more natural to use “var” rather than the official type definitions. I can see their points as well.
I also sensed that “var” was more often used with “newer” developers. The “seasoned” gray-haired developers with more years of experience such a working with .NET 1.0, C/C++, or Java may prefer being more specific with their data types.
Here is a code example that I presented the Intertech consultants. It’s from a Microsoft course that I teach.
// Instantiate a type var type = FourthCoffeeServices.GetHandleErrorType(); ... var constructor = type.GetConstructor(new Type[0])); ... var initializedObject = constructor.Invoke(new object[0]); // Invoke methods on the instance var methodToExecute = type.GetMethod("LogError"); var initializedObject = FourthCoffeeServices.InstantiateHandleErrorType(); ... var response = methodToExecute.Invoke(initializedObject, new object[] { "Error message" }) as string; // Get or set property values on the instance var property = type.GetProperty("LastErrorMessage"); var initializedObject = FourthCoffeeServices.InstantiateHandleErrorType(); ... var lastErrorMessage = property.GetValue(initializedObject) as string;
As a full time MCT trainer, I think this is code is not helpful at all for teaching reflection to new C# developers. I have actually changed the slides to help students learn. It now looks like this:
// Instantiate a type Type type = FourthCoffeeServices.GetHandleErrorType(); ... ConstructorInfo constructor = type.GetConstructor(new Type[0])); ... object initializedObject = constructor.Invoke(new object[0]); // Invoke methods on the instance MethodInfo methodToExecute = type.GetMethod("LogError"); object initializedObject = FourthCoffeeServices.InstantiateHandleErrorType(); ... object response = methodToExecute.Invoke(initializedObject, new object[] { "Error message“ }) as string; // Get or set property values on the instance PropertyInfo property = type.GetProperty(“LastErrorMessage"); object initializedObject = FourthCoffeeServices.InstantiateHandleErrorType(); ... string lastErrorMessage = property.GetValue(initializedObject) as string;
I think the second example is clearer for students but I can also see how it does appear more cluttered. I strongly believe that if a developer insists on using “var” local variables as return types for methods, they need to be sure to name the variables descriptively and (if possible) name the methods descriptively as well.
Here is another example I presented to them. Yes, I admit that I had to research all the numeric suffixes to write this code. Yeah – I (unfairly) asked them if they could tell me the data types to the variables Numb1 through Numb9.
int iRowCount = 1234; // Explicit declaration var iColCount = 1234; // Implicit declaration //var iTotal; // This is illegal. //var Obj1 = null; // So is this. var Numb1 = 123D; var Numb2 = 1.2E+3; var Numb3 = 123F; var Numb4 = 123M; var Numb5 = 4294967295U; var Numb6 = 8589934590U; var Numb7 = 9223372036854775807L; var Numb8 = 18446744073709551615L; var Numb9 = 18446744073709551615; Console.WriteLine("123D is {0}", Numb1.GetType()); Console.WriteLine("1.2E+3 is {0}", Numb2.GetType()); Console.WriteLine("123F is {0}", Numb3.GetType()); Console.WriteLine("123M is {0}", Numb4.GetType()); Console.WriteLine("4294967295U is {0}", Numb5.GetType()); Console.WriteLine("8589934590U is {0}", Numb6.GetType()); Console.WriteLine(" 9223372036854775807L is {0}", Numb7.GetType()); Console.WriteLine("18446744073709551615L is {0}", Numb8.GetType()); Console.WriteLine("18446744073709551615 is {0}", Numb9.GetType());
Of course they couldn’t and I don’t blame them for not having all the numeric suffixes and type boundary sizes memorized.
One developer told me that these are terrible variable names (agreed!) and should have names that describe their types. Another developer told me they’d fire the developer that cut this code – LOL!
For the curious, here is what is returned.
Incidently, JetBrains Resharper suggests using “var” with variable declarations by default.
However, is can be simply turned in its configuration setting under Tools | Options… | Resharper Options.
No matter how little or how much you use “var”, I want you to keep something in mind. By using “var”, you are giving full control of how a variable will be defined to someone else. You are depending on the C# compiler to determine the datatype of your local variable – not you. You are depending on the code inside the compiler – someone else’s code outside of your code to determine your data type.
Consider how the compiler works. When it encounters a “var” statement, it understands that it is the responsibility of the compiler to determine the correct data type. If it cannot, it will responsibly raise a compile (build) error. The compiler must follow a specific algorithm that has been written into it to determine the correct data type. The developer is dependent on the code’s algorithm in the compiler to run correctly and determine the correct data type rather than the developer explicitly defining the variable directly. You can certainly study this complex algorithm is the C# compilers’ source code located in the Roslyn project, here: https://github.com/dotnet/roslyn/wiki
Unfortunately, the compiler isn’t always going to determine the correct type or the type you are expecting and this can be a source for errors. After my Yammer conversations with the Intertech consultants, I spoke with one of the Intertech senior developers offline (one on one) about a bug that cost him a couple of hours while slaying it. A variable that was declared as “var” was being assigned a different data type than he was expecting. I suspect there are seasoned C# developers reading this that may have experienced the same thing.
I am sure there are other things I will realize I should have added to this article but these are some of the most important point I wanted to stress here. Thank you for reading and considering. Many thanks also to the Intertech consulting team! Cheers!
Very nice and helpful article!
I only use the fully qualified type when visually (by a human), the type inferred by the var keyword is ambiguous. The only case I see is when there is no “new” keyword used to instanciate the variable like create using the result of a method, a factory, etc…
In all other cases, the var keyboard have both the ability to reduce the number of keys I type on my keyboard and also declutter the code helping to understand faster the code.
Note that I only apply these rules to reference type. In other words, I always use a fully qualified type for value types like “int”, “decimal” and “string” even though “string” is considered like a reference type 🙂
I can’t believe there aren’t many comments on this. Yes, I totally agree with you. It’s just that “some” companies followed some books blindly and makes it a coding standard and when some junior programmers catch you not using var instantiating an object in a code review making you look bad in front of the manager, it’s just a bunch of nuisances wasting resources in the long run. My defense is this, that’s the first thing you see in a line and it means that I’m expecting this type of object to be created. To use var is when you have an anonymous type usually from a collection or linq. I think this practice of var was coming from javascript or perl where the compiler knows what type to create or even VB. Like var a = “hello” var b = 14; This kind of tie to Hungarian notation. I found it useful when I look at a variable down the code. I can “assume” what type of variable it is. Like a strFirstName, versus a arrayListNames. I know I won’t mixed up which goes where.
I’ve seen the kind of problems noted above when expecting a list and the compiler returns an iterator or other cases when it returns based on an underlying interface that I had not considered. These are minor problems for senior developers but black holes for the less experienced.
I’ll restate what both you and @Mystcreater:disqus said: If I know the data type being returned, then I use var such as in the case of a constructor or a typed value being passed into a function. I use var when writing linq because to not do so is insane (that’s the point of linq, it’s dynamic!). If I’m returning from an API that is not part of the .Net Framework, I always use a type. The last point has saved me when I’ve accidentally changed the API or worse, was returning the wrong subclass.