04 March 2008

Varification -- Using Implicitly Typed Locals

With the ReSharper 4 nightly builds available, some people are complaining about numerious suggestions to convert explicit type to "var" keyword. Of course, you can hide this suggestion by using Options / Code Inspection / Inspection Severity, or by using Alt-Enter and selecting "Change severity" option. But what's the deal with implicitly typed locals, anyway? Using var keyword can significantly improve your code, not just save you some typing. However, it may require discipline to apply good practices when using implicitly typed variables. Here is my list:

It is required to express variables of anonymous type. This is pretty obvious - you cannot declare local variable of anonymous type without using var.

It induces better naming for local variables. When you read local variable declaration with explicit type, you have more information at that moment and something like "IUnitTestElement current" makes sense. However, when this local variable is used later, you read "current" which takes some time to figure out the meaning. Using "var currentElement" makes it easier to read at any place.

It induces better API. When you let compiler deduce type from method return type or property type, you have to have good types in the first place. When you don't have explicit type in the initialization expression, you have to have best names for members.

It induces variable initialization. It is generally a good practice to initialize variable in the declaration, and compiler needs initializer to infer type for local variable declared with "var" keyword.

It removes code noise. There are a lot of cases, when implicitly typed local will reduce amount of text developer needs to read, or rather skip. Declaring local variable from new object expression or cast expression requires specifying type twice, if we don't use "var". With generics it can lead to a lot of otherwise redundant code. Another example would be iteration variable in foreach over Dictionary<TKey,TValue>.

It doesn't require using directive. With var, you don't have explicit reference to type, as compiler infers type for you, so you don't need to import namespace when you need a temporary variable.

To summarize the list above, by actively using var keyword and refactoring your code as needed you improve the way your code speaks for itself.

52 comments:

“Overuse of var can make source code less readable for others. It is recommended to use var only when it is necessary, that is, when the variable will be used to store an anonymous type or a collection of anonymous types.”

For all the times I've agreed with you, this time I'm not convinced. The argument that it forces better naming conventions just doesn't work for me. I want good naming conventions from my developers whether or not var is involved (and Resharper really helps with make that easy!).

Other than for the obvious use with anonymous types, which the use of var can help highlight, and the perhaps simple variable initialization:

var name = "Ilya";

or

var currentIndex = 1;

I'm not sure I favor it. When I see:

var latestUpdate = GetLatest():

it doesn't tell me what latestUpdate returns.

I'm just moving projects to 3.0 so I'm keeping an open mind on this. I'm wondering if you are considering allowing configuration of the var suggestion only in the case of simple initialization?

“Overuse of var can make source code less readable for others. It is recommended to use var only when it is necessary, that is, when the variable will be used to store an anonymous type or a collection of anonymous types.”

I agree with Alexander. Var should only be used for anonymous types. It was designed for anonymous types and for use with LINQ. Using var to implicitly type local variables is not good practice and makes code more unreadable.

I'm keeping an open mind... Here's a post by Rob Conery which contains some additional thoughts:

"The upshot here is that vars generate some serious code - all for good reason when using LINQ. But NOT for a good reason if you’re being lazy - which is the point of this whole post. If you find yourself using “var” anywhere that’s not within a LINQ statement, it’s probably not a good idea."

The last was one I'd not quite registered consciously, although now that I think back over the past 6 months of steadily increasing use of var, I think it's definitely been an influencing factor...

Jeff:

Just FYI, and putting aside the renaming possibility for the moment, in my experience I've actually found it really useful to be able to implicitly change the return type of these sorts of creational/factory methods. If at some point later you that an extract interface / split interface/class refactoring is appropriate (perhaps 80% of usage is of a logical subset of the original interface) then implicit typing can reduce the amount of manual change in some scenarios...

To borrow from your example, you may decide to split the LatestUpdate into an interface providing meta-data only, and another one containing the full content of the update... If most usage just needs the MetaDataForUpdate interface/class, the GetLatest can just return that... With implicit typing, you avoid having to change the locals calling this method, but the compiler will still catch the 20% of usages that actually need the full ContentOfUpdate (because they are attempting to call a FileBytes property which does not exist on MetaDataForUpdate), and you can just work on that smaller proportion of code.

During refactoring, it almost acts like a strongly-typed version of Duck-typing (http://en.wikipedia.org/wiki/Duck_typing)

This is definitely a minor scenario, and despite the length this comment ended up being :), I don't mean to overstate it... BUT it can be quite convenient.

Most commonly I've found it useful when trying to increase unit test coverage in existing codebases, where there may be numerous existing tests that each create an instance. Here, running extract interface to facilitate a mock or fake implementation becomes just a little bit easier... For an example, see below.

(Of course, horses for courses, and it won't appeal to those who like both suspenders and a belt... :)

Matt

We can change

class Duck{ void TalkQuack(); void WalkWaddle();}

Duck CreateDuckInstance() { return new Duck(); }

// line of code that exists in N unit tests...var speaker = CreateDuckInstance()

I really am having a hard time to read code with too many vars - it's just a reduction of information. While you may say that it "forces" devs to go with better variable names, I'd still opt for explicity typing *and* good variables (and people who don't care will still use bad naming schemes)...

-Do use var for anonymous type -Do use var for constructorseg var list = new List();-Do use var for castseg var Ilist = (IList)list;-Consider using var where the variable name implies the type of the variavleeg var xmlSerializer = GetXmlSerializer();

The idea is to use var where it does not obfuscate the code

With these in mind it would be great if in the resharper config we could define different cases when the var hint is shown.

Before var existed, was anyone in the community thinking "my code would be so much more readable if only I didn't have to type all my local variables"? No, of course not. It was pretty much invented only to support Linq. The fact that it can be used for non-anonymous types doesn't mean it should.

Indeed, I feel your points are mainly spurious. For example, points 2, 3 & 4 are essentially saying "because some coders follow porr practices, everyone should remove useful information from the code". While point 5 refers to the useful information as "noise". The compiler can infer the type, yes. Poor maintainers, however, shouldn't have to work to do this, they should see it explicitly stated.

Who are all of these people that are scrolling back up to the variable declaration or using "Go to declaration" to determine the type of a variable rather than simply hovering over the variable?

Are you guys using something other than Visual Studio for C# development? Monodevelop, perhaps? Doesn't it provide similar features?

It seems to me the flexibility and the Don't Repeat Yourself (DRY) principal demand var usuage wherever possible, and I don't see how this adversely affects practical readability if your variables and APIs have descriptive names.

If you are relying on the variable type to make your program more readable, then you aren't using descriptive enough names. Besides, that also implies that knowing the variable's type affects how you use it, rather than simply using IntelliSense to go member-shopping, as I'd bet most of you do anyway.

It just seems goofy to pretend that you are programming with vim, emacs or notepad, when the IDE takes care of any practical concerns introduced by var declarations.

I think that using "var" (type inference) is also consistent with modern functional programming ideas realized by such languages as Scala and F#.In Programming in Scala Martin Odersky emphasize on howval greetStrings = new Array[String](3)is generally better thanval greetStrings: Array[String] = new Array[String](3)because it does not repeat unnecessary Array[String] (both styles are valid in Scala).

P.S. I basically agree with what Brian said. Most of the time DRY applies, but as Martin Odersky likes to say, "had you been in a more explicit mood, you could have specified the type ... explicitly" :)

BTW, C#, F#, and Scala are better here, than Ruby, because they still use static types.

From the points made in the main article it seems this type of refactoring is unique amongst all the great recommendations that resharper makes. This rule makes your code worse until you can manually refactor or rename existing code to add in some meaning that has been removed.

Reshaper is a great tool because it simply lets me refactor code to be better with a few mouse clicks. I don't think resharper would be as great if it had a bunch of rules that only took you halfway to the goal.

I think the decision to keep this feature is a philosophical decision for the Resharper dev team. Are these halfway rules what you want to include into your otherwise concise and complete rule set.

Personally i don't like this rule. If a member of my team used a "var" where it wasn't necessary i would ask them to change it. I would actually like a reverse rule for this. "Don't use unnecessary implicitly typed locals"

I've turned off this recommendation and am telling my developers to do the same. Variable type declaration is not equal to variable instantiation. Therefore, you should only use var when you must. I've fought far to many battles in classic ASP and vbscript where the type I thought was going into the variable wasn't the type I ended up with.

How do you know if the message is an IMesssage, Message of even just a string?

You say that I should rename my method....do I have to call it Inbox.GetIMessage() or even worst...Inbox.GetStringMessage()???

And by the way, maybe I dno't even have access to this code..maybe iI' using a dll from another provider. You should NEVER change your coding convention because of that.

Naming all your method depending on the return type is totally stupid. That's exactly why Microsoft says to not overuse the var keyword. I agree that var should (could) be used when declaring long named type objects like in this example.

//this is long for nothingMessageProvider messageProvider = new MessageProvider();

//this is okvar messageProvider = new MessageProvider();

It should also be used with LINQ. But THATS IT! Don't use it with method. Don't use it inside loops. Stop using var just because you can. If you don't like strongly typed language, go with Ruby or Python and stop blogging about C#.

"How do you know if the message is an IMesssage, Message of even just a string?"

You hover over the variable name. But you probably don't even need to do that, unless you have memorized the entire API/library, which would be a waste of time. In reality, you type the variable name, then a dot, then you shop for the property or method you need, just like everything else.

I hardly ever agree with MS on anything related to development, ... but I have to agree with them on the overuse of var. Why must I hover over variables? I use a laptop most times without a mouse. It's easier for me to read IInterface interface = api.apiMethod() than var interface = api.apiMethod() and judging by the debate all over the net, I'm far from being the only one who prefers it that way.

Appeals to popularity aside, I assume anyone with a problem with var explicitly casts all of their expressions and method params to the appropriate data type, too, so they can clearly see the type. It'd be critical since they've all memorized the entire (current) API, rather than typing a simple dot when they need to access a type member and shopping for it with IntelliSense.

Anyone that dislikes var is going to be completely unable to approach F#.

var should be used for all complex types, and subjectively used for primitive types.

The quote that Alexander posted “Overuse of var can make source code less readable for others. It is recommended to use var only when it is necessary, that is, when the variable will be used to store an anonymous type or a collection of anonymous types.” appears to have been redacted and replaced by a statement that is vastly different. "However, 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." Can be found on http://msdn.microsoft.com/en-us/library/bb384061.aspx Even this argument is mostly dubious but does make sense for a documentation site like the MSDN.

If the var makes your code less readable it is YOUR FAULT for BAD NAMING of variables.

"C# documentation generally uses var only when it is required"This is a bit obsolete approach intended for people who are completely new and unaware of ideas of functional programming, type inference, etc. After reading some books on F#, Scala, etc. (one of my favorites is http://www.functional-programming.net/) it becomes clear when to use and when not to use var. With constructors and type casting operators it doesn't make sense to use explicit types - just makes code less readable. Var also makes sense to use in all cases when type is clear from a context, when type is automatically generated and/or very complicated.

To me, anonymous variables is a retrograde step to object type Variant, when it became so confusing as to what the object contained, Hungarian notation was the preferred method of identifying type, so instead of

Int32 count;

You would instead have

var iCount;

It also leads to numerous coding errors where there are now assumptions about what type is being assigned, where you were expecting one type and got another. Explicit casting prevents invalid runtime assignments, immediately in the IDE. Instead, you would have to debug trace through, to realize the point of failure, was assigning your Variant the wrong object 20 steps before an exception was thrown.

No. there's a good reason for explicit types and nothing more than lazy coding for anonymous types (Variants)

Stop poisoning the world with this nonsense, on top of making code less readable, using var everywhere is just plain LAZY - don't like to type - then find another job because I am sick of walking into gig's where people seem to think this crap is the way to go.

Just because you can drive a car with your feet doesn't mean you should.

Seems that coding OO is not what it used to be...Maybe an interface to the developer brain to avoid all typing? And linked to the user, no more coding and compiling... Telepathy... :)Now that was unnecessary, I apologisze, so should MS for trying to attract all the web masters that know some javascript, are unable to think in abstractions and to whom writing(literally)/reading code (my precious) is too hard.The problem with giving kids candy is that unless you hide the jar and feed them candy yourself, they don't know when to stop...And yes, I do use var! sensibly, I hope... when I don't know the name of the type and then hoover over the var to get the proper type :D... great tool! (also on using()...)But hey! Don't let me stop you from coding as you feel like it. If there was only one way of coding and it was the right one, we would not have this conversation at all. And testers do need work:)

I very much disagree with this. If this is so then C# should decide about it NOT some tool added on top. C# is saying why var is there and the circumstances when it should be used. Being smart over the language specification is never a good idea.var list = new List() might have some sense especially when declaration type is very long, but dragging it into using var just about everywhere is something I totally disagree. In order to read the type you have to dig into the code. That does not have any sense. If C# wanted that, they would tell you to do that.The problem is that doing it indiscriminately can lead to a serious issues. Take this code

var spaceWidth = count == 0 ? (decimal?)a : null;

Intention is to have spaceWidth to be decimal? yet this is declared within the code Yes this is exactly what a developer would do if he would see decimal? spaceWidth = since var by Refactor has to be used everywhere.