This is a great question for a junior developer. Not necessarily that the asker is junior, but that ensuring clarification prior to presenting information to a junior developer is a great thing to do.
In that spirit, whoever finds this question should always understand that readability is one of a few Quality Attributes, and certainly one of the most important to master early on. Readability includes variable naming practices and explicit code, to name a couple.
That said, one individual micro-aspect of readability is whether or not to use implicit typing via the var
keyword. The short answer is Maybe. An educated answer with examples might narrow Maybe down to Rarely.
So, to make this easiest to understand, I'm going to begin with reasons not to use implicity typing via the var
keyword.
(Language Perspective) The first reason not to use implicit typing is because a major strength of C# is that it is a strongly typed language. There are plenty of wonderful languages whose strengths include NOT being strongly typed such as Javascript. Every language is different and has its own strengths/weaknesses. For C#, being strongly-typed is one of its most important strengths.
This answer assumes that your code is SOLID. If you are working in a legacy code-base, or are a junior developer who hasn't quite achieved full focus on dependency injection or Liskov Substitution, then micro-tuning your var
usage isn't where your focus should be right now.
There are only a few ways to assign to a variable. These are the ones I think of right now:
ISomething someVar = new Concrete(); // <1. Can't use var to create Interfaces.
var someVar = GetFromMethod(); // <-- 2. Taken from return type
var someVar = new MyPerson(); // <-- 3. Custom complex reference type
var someVar = new DateTime(); // <-- 4. Built-in simple Reference Type
var someVar = string.Empty; // <-- <<
var someVar = new List<T>(); // <-- 5. Built-in complex Reference Type
var someVar = new Dictionary<string, Dictionary<int, List<MyObject>>>();
var someVar = true; // <-- 6. simple Value type assignment
var someVar = 1; // <-- 7. complex Value type assignment(s)
var someVar = 1.0; // <-- <<
var someVar = 1.0d; // <-- <<
foreach (var i = 0; i <= . . .) // <-- 8. Same as 7 above, but different context.
var someVar = new {Name = "yo"}; // <-- 9. Instantiate Anonymous Type
(Breakdown)
1. In example 1 of the above examples, I illustrate the only time you simply cannot use the var keyword. You obviously can't create a concrete instantiation under an Interface. I get into more specifics about using Interfaces in #5. Don't Can't use var here
2. Example 2 assumes somebody is using the same development tools as you, and that everybody wants to take the time while reading code to investigate the return-type of methods. Depending on how fast you read code or code-review, this could be an insignificant or a major drawback. Don't use var here
3. Why are you instantiating a newable in-line? As I said earlier, these examples assume you practice SOLID principles. This way of declaring a variable creates a code smell. If you search your codebase for the new
keyword, the only results should be in auto-generated code, a composition root, or for #4 below. Don't use var here ever do this
4. new DateTime();
, and a couple other rare Built-In simple types are some of the rare times you should see the new
keyword in your codebase. Using the var
keyword in example 4 isn't that big of a deal. But honestly, what are you buying by fighting to be implicit in this situation? Same question for the string. Can use var here... but why?
5. You should always try to use the least specific type possible. In short, that means use small interfaces. This rule mostly applies to external-facing API's because you want to keep changes as flexible as possible without breaking a consumer. The only reason this rule is NOT strictly applied to internal code because if a developer wants to make a breaking change, they have the capability to take extra time and do extra work to cascade break-fixes. That's not a very good excuse.
.....5.1 So for the first part, note that someVar becomes the type Generic.List<T>
. If you're wanting to create a variable of type IList
, as I can see you do, then using the var
keyword is not what you want. This is generally the rule for declaring variables with the least specific type possible. Look at: IList vs List. What if you purposely don't want to allow the usage of your variable to include all that extra junk in List<T>
? There's a reason for these rules. Try Not to use the var keyword if you can follow this rule.
.....5.2 Assuming you don't care, or don't want to use interfaces as suggested, this is fine. This also somewhat applies to the idea of length. If you have nested levels of collections and your declaration is long, nobody would blame you for using the var
keyword. Okay if you aren't using Interfaces
6. This is similar to example #7, but applies to Non-Numeric value types. The simple question is, "Why?" Just as I said in #4, what are you buying? Assuming you are going with the Default value, you'll have to specify the type anyway. Why mix rules, and what does it buy? Sure, but why?
E.G.: You have to be explicit sometimes anyway, why mix rules?:
bool isVarOkay, canUseVar;
char a, b, c, d, e, f;
bool isSample = true;
byte etc;
var isOtherSample = true; //<-- why?
7. There are a bunch of numeric value types. Most of the reasoning for that is for precision, and some is for semantic purposes. Either way, why let the compiler guess at what you want instead of being explicit. If there was ever a time to be explicit, numeric value types is the time. As far as plain-ol int
goes, perhaps there is some leeway to use var since it is so direct and obvious. But I'd rather save that for point #8. Don't use the var keyword
8. This code structure is used in so many places, that it almost seems okay to do it. But once again: Why, and what are you saving? var
and int
are both 3 characters. Sure, but why?
9. In the case of Anonymous returns, you almost have to use the var keyword. Not doing so sort of defeats the purpose of being Anonymous. Most Anonymous types can be inlined so that their results are immediately transformed into something useful, so they don't necessarily have to be assigned to a variable. But there are some occassions for this that are not worth avoiding. Use var for Anonymous Types if necessary.
Conclusion
The var
keyword is unavoidable for Anonymous types. Also, it can be helpful for Generic types with multiple levels of generics which make for a long declaration like Dmitry's example Dictionary<string, Dictionary<int, List<MyObject>>>
. Lastly, it wouldn't hurt anybody's feelings if you use the var
keyword in the examples shown in numbers 4, 5, 6, and 8. But you aren't buying anything.
The idea that using the var
keyword allows you to change the type, or allows you to stick to the DRY principle, is nothing but a bogus excuse. Only in rare situations does the Assignment-side of the declaration properly represent what the Type is supposed to be.