Home > C# > In Defense of ‘var’

In Defense of ‘var’

The var keywords has unfairly earned a bad reputation. I see a lot of a hating on var, and don’t hear many people sticking up for it. If you don’t like var, or know someone who does, then this post is for you.

My mom was born left-handed. The nuns at the Catholic school she attended objected to this. Whenever she used her left hand, say to write with a pencil or cut paper with scissors, a nun would hit my mom’s left hand with a switch. They made her become right-handed, despite the fact that there is nothing inherently better about being dominant with either hand. Food is not more nutritious when eaten with your right-hand. Words are not more expressive when written with your left-hand. The universe does not care which hand you use (even though it does seem to care about the handedness of matter). Any benefit or detriment to being a “righty” derives from the fact that lots of other people are right-handed, or from other facts for which handedness merely stands as proxy (for example, brain hemisphere dominance in certain tasks). In fact, being left-handed is considered an advantage in some socially valued activities precisely because it is less common that being right-handed. Again, this slight advantage has nothing to do with being a “southpaw” per se. It wouldn’t be an advantage if 90% of people left-handed and only 10% right-handed.

Most of us never bother to consider all this, but once you do, it makes sense. Just like the universe doesn’t care whether you are left-handed or right-handed, the .NET compiler doesn’t care whether you use var or not (with two exceptions noted below). It isn’t inherently worse or better. It’s utility depends on how you work best. For some, it cuts against the grain. For others, it cuts with the grain. If being a lefty is analogous to using var, then why are so many coders right-handed? I can’t say entirely, but I do believe it’s in part because nuns keep rapping the knuckles of developers when they opt to use it (ReSharper excluded).

I really only feel strongly about it because I think (a) it’s such a small thing that most people can’t be bothered to think much about it, and (b) as a result of (a), many people give too much credence to the opinions of “authorities” who weigh-in on the topic. I don’t want to rehash prior discussions on the topic, but I do want to distill down my view on the issue. Hopefully it will at least provide an entry point for some into even *having* a discussion. It’s okay to be use var. It’s not your fault.

So, I want to begin with laying out the standard arguments *against* using var (for anything other than anonymous types). I don’t want to attack straw men, here, so I’m trying to be accurate. Call me out if I miss my mark.

  1. var makes code less readable. To determine a variable’s type when using var, I’m required either to apply the same type inference logic that the compiler uses, or become dependent on an IDE’s Intellisense/autocomplete feature.
  2. var makes refactoring more difficult. To change the type of every MyClass variable, I just need to /MyClass/MyNewClass/g and I’m done; whereas with var I will miss instances where the type was inferred from the return type of a method call.
  3. var makes debugging more difficult. Because of (1), there is a category of bugs that won’t be caught until runtime, and where the exception will not intuitively relate to the underlying problem.

Here are my counterarguments:

  1. This depends on what you consider “readable”, and in general I find the first line more “readable” (especially if you also do a fair amount of javascript):

    // Don't lie: which variable name can you spot faster?
    // Focus my cognitive load only on the constructor call.
    var lookupTable = new Dictionary<String,Func<Int,MyClass>>();
    // Does the type declaration exactly match the constructor's class?
    // It's going to take some mental effort to see.
    Dictionary<String,Func<Int,MyClass>> lookupTable = new Dictionary<String,Func<Int,MyClass>>();
    // I also find using interfaces clearer when using vars as well.
    var instance = new MyRepository() as IRepository;
    // Instead of:
    IRepository instance = new MyRepository();
    // This doesn't help me if MyRepository 
    // actually implements IRepository<T>.

    Considering nobody wants to type that loooong type name twice, most mortals will rely on autocomplete to avoid typing the entire thing anyways, so there is no great disadvantage there to using var in the first place. I also find myself wanting to start abbreviate/shorten longer, but more descriptive, type names when I don’t use var quite so much. It just gets fatiguing, and feels like my own code is “getting in my way”. I’ll take ObservableCollection over ObsColl when reading someone else’s code (or my own, six months later).
    In addition, I believe you should know the compiler’s type inference rules, and should be applying them every time you do an assignment–regardless of the style you’re opting for. If you can’t readily make out the type on the right side of assignment operator (I’m looking at you, overly-complicated LINQ expressions), then you have a code smell and probably need to refactor (e.g. to a method group).

  2. Take the following example:

    // Suppose:
    IRepository instance = Repository.Create(typeof(MyClass));
    // If I refactor MyRepository() to implement
    // the generic interface, I now have to refactor
    // my variable types as well. If I had just done:
    var instance = Repository.Create(typeof(MyClass));
    // Then I would be fine.

    I argue that using var avoids a DRY violation. In fact, I actually like the fact that I can refactor a method return type without changing the variable declaration. Instead of the compiler complaining about the variable name not matching, it skips straight to all of the places where the new contract differs from the old contract. Declaring the variable type doesn’t avoid this, it just adds an additional compiler error noise. In general, I find the when using var when I don’t have to, I am paying closer attention to contracts and variable names–just the things I should be paying attention to.

  3. I’m not going to argue too much against the example raised in the linked article. It’s an edge case for me, and in general, I find this to not really be a problem. My first question would be “why is the compiler think the result is a long instead of an int?” This would be the exact question that I would ask myself if I got a the error message at compile-time instead of run-time.
    However, consider the following function f:

    Func<int> f = ()=>; 
        uint unsignedNumber = 42;
        int signedNumber = 10;
        var result = unsignedNumber * signedNumber;
        return result; 

    Attempting to compile this snippet results in the following compiler errors:

    • Cannot convert lambda expression to delegate type ‘System.Func’ because some of the return types in the block are not implicitly convertible to the delegate return type
    • Cannot implicitly convert type ‘long’ to ‘int’. An explicit conversion exists (are you missing a cast?)

    So, this var “fail” is even more of an edge case than presented originally.

  4. Soooo…

    I am not so much seeking to win converts over to using var as I hope people will begin to see this is as, at least, a style and preference issue–and not as an issue of right or wrong. Do I prefer var? You betcha! Do I look down on those who don’t? No, I get it. I’m just too lazy to do all that typing. Honestly, I’d rather save my finger strength for more coding. Or even–GASP!–blogging.

Oh, and the caveats mentioned above?

  • If you are writing code against 2.0, then you obviously can’t use var. If you are going back in forth between say, 2.0 and 4.0, then I can absolutely appreciate wanting your fingers to remember just the one way.
  • If you are using anonymous types, or Linq, then you have to use var. Just like above, if you do a reasonable amount of either, then I can absolutely appreciate wanting your fingers to remember just the one way.
  1. No comments yet.
  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: