Brendan Enrick's Blog

Daily Software Development.


15 Comments
Tagged as: ,

Overusing var in C#

With C# 3.0 came one new feature I both love and hate; the implicitly typed local variable: var. I think it is great because it is implicitly typed, but it is still strongly typed. At compile time it will be the explicit type as if you had typed the actual type name. Visual Studio is able to determine during development what the type is, so there isn't much of a downside. However, I believe it gets overused.

I think it is great if the line contains the "new" keyword, because I can already see the type name because it gets written for the constructor. Using "var" all the time really irks me though. It is inconvenient, because I can't always tell what type the variable is. This isn't always too much of an issue, but I prefer defining the type when possible.

For generics it is great since those type names get quite long. With generics we define two types together, so with longer names this sometimes becomes a little unwieldy. This is one of the great strengths of this new behavior in C#.

Earlier today I was reading an interesting post from Jimmy Bogard. He was blogging about The Filter-View anti-pattern. What bugged me about the post was his use of var. Now I know this has nothing to do with the actual post itself, but who can resist posting about their coding preferences?

In the post he had this code snippet.

public class ProductController : Controller
{
    [LoginInfo]
    public ActionResult Index()
    {
        var products = _productRepository.FindAll();

        return View(products);
    }

Now can you tell me what type is the variable products? Sure you might guess a collection of Product objects. You're probably right. Is it an IEnumerable? Is it an array? Is it a list? No, you don't know for certain. In fact you can't be sure it is a collection of Product objects. What if it were a collection of product names? That could be a badly named method and you get back strings.

You might think I am stretching a bit there on the strings, but there certainly could be methods which just didn't clarify well enough in there name. Now I know that I can mouse over the type in Visual Studio and instantly find out what type it is, but I should have to. In fact I probably wouldn't. I would probably try to use it and be kind of annoyed. Odds are I would have made an assumption on what type it is, and then I might have been annoyed when I tried to use Length thinking it was an array and then found our it was a List and I needed to use Count.

Anyway, I do recommend reading blog posts from Jimmy Bogard even though he overuses the implicitly typed local variable in his code snippets.

kick it on DotNetKicks.com

Trackbacks & Pingbacks

Daily tech links for .net and related technologies - June 19-23, 2009 — 23 Jun 2009 1:06 AM

Daily tech links for .net and related technologies - June 19-23, 2009 Web Development Rapid Application


The Technology Post for June 22nd, 2009 | rapid-DEV.net — 23 Jun 2009 3:06 AM

Pingback from The Technology Post for June 22nd, 2009 | rapid-DEV.net


I love .NET! » Blog Archive » The Technology Post for June 22nd, 2009 — 23 Jun 2009 11:43 AM

Pingback from I love .NET! » Blog Archive » The Technology Post for June 22nd, 2009


Trackback link for this post:
http://brendan.enrick.com/trackback.ashx?id=172

Comments

 avatar

Rik Hemsley said on 23 Jun 2009 at 7:09 AM

If I wasn't keeping a local reference to the return value, how would I know from glancing at the code what type was returned by FindAll()?

Of course I can't know for sure. But I should assume it is at least IEnumerable<Product>. If it's not, that's a problem with the naming of the method.

If I am storing the return value of FindAll() in a variable named products, I should expect that products contains at least IEnumerable<Product>. If not, that's a problem with the naming of the variable.

This has nothing to do with var. If you have bad naming, you have a problem.

benrick avatar

Brendan Enrick said on 23 Jun 2009 at 9:00 AM

Sure, you're right. Methods are named badly if you can't tell the type they're going to return. Generally when I find code like this it is in some project or snippet written by someone on the Internet.

Perhaps I am just a developer who started developing with C++ and doesn't want to drop that old convention, but I prefer seeing the type there.

 avatar

Karthik Hariharan said on 23 Jun 2009 at 4:08 PM

My rule of thumb is that var is okay if returning a reference type or collection. The method name and variable name should be intuitive enough to figure it out.

If the method is returning a primitive, using var hides the return value and can affect things like precision if returning a decimal/double.

 avatar

len smith said on 23 Jun 2009 at 6:19 PM

WhatAreYouTalkingAbout whatAreYouTalkingAbout = new WhatAreYouTalkingAbout();

var saves space. it's easier to read.

it's not very often that you both won't know the type and it is actually important. for those times just use the power in your ide instead of making me read more crap.

 avatar

Gareth Rowlands said on 25 Jun 2009 at 2:01 PM

Len's right. The type of 'products' in this method is not important. It's perfectly clear what the method does and wouldn't be any clearer if it was longer.

Furthermore, the code expresses the programmer's *intent* perfectly: it returns all the products from the repository for display. It doesn't matter whether the products are of type ProductCollection or IProduct or whatever, in the same way that it doesn't matter when the JIT calls malloc. Sure types are important (and so's memory management) but you want to be able to abstract that stuff away.

Types *are* really important to larger scale structure - a UML class diagram wouldn't be much use without class names. But 'var' doesn't threaten any of that (again, using UML class diagrams as an approximation for 'important stuff', notice that C# wouldn't let you use var anywhere where it might appear on a class diagram).

benrick avatar

Brendan Enrick said on 25 Jun 2009 at 3:35 PM

Yes, you're correct that it doesn't allow you to use var anywhere it would be truly ambiguous since it is local only.

I completely agree with Len's example. When the type name is already on the line I always use var.

I think that if you need to shorten the line by using var as the type then you're line should probably be shortened somewhere else if possible.

I use var often, but I think people have adopted it too easily and are using it more often than is necessary.

 avatar

zihotki said on 25 Jun 2009 at 4:44 PM

var products = _productRepository.FindAll(); - var is at least of IEnumerable<Product> type and I don't need to know any additional information about result in this case. It's enough to know that it will be IEnumerable<Product>.

Probably you need to use more suitable names for methods when you can't see the returning type.

I prefer to use var wherever it can be used because in my opinion it improves code readability (e.g. lines are more compact and there are less noise).

benrick avatar

Brendan Enrick said on 25 Jun 2009 at 5:26 PM

Thanks for the comments everyone. I think we are all in agreement that var can be used to clearly and concisely write code.

Let me pose a quick question for you. What is the return type here?

var perc = winTracker.GetWinPercent();

Probably a value type. Not sure if it is between 0 and 100 or 0.0 and 1.0. I would assume since int and var are same length that it is probably not int. Is it a Double? Decimal? Single?

 avatar

Gareth Rowlands said on 26 Jun 2009 at 8:52 AM

Well precision can really matter, so I'd probably spell out the type of 'perc' too.

Mind you, if I saw this:

double perc = winTracker.GetWinPercent();

I'd probably think GetWinPercent returned double. But it could still legally return int (so 50 means 50%) due to implicit conversions. So maybe spelling out the type of 'perc' didn't do me as much good as I'd thought... :-)

Btw, my perspective on type systems and type inference has been influenced by programming with Haskell recently. Haskell has lots of type inference but never ever converts implicitly.

 avatar

Mike said on 26 Jun 2009 at 11:48 AM

OK, var is quicker and easier to read, but it's also vague and imprecise.

I can see where it would be handy for rapid prototyping, but if we're trying to write maintainable software it's far too vague and sloppy IMO. I think the very discussion on this comment thread indicates why it's bad design from a readability standpoint - it's cleaner from a line length point of view, but its less clear from a human interpretation point of view.

 avatar

Scott DePouw said on 09 Jul 2009 at 8:09 AM

Another consideration to make is that using var will prevent one from programming against an interface versus a concrete implementation.

public class MyConcreteRepositoryImpl : IRepository

{

// ...

}

var myRepository = new ConcreteRepositoryImpl();

myRepository is now of type ConcreteRepositoryImpl instead of the interface type IRepository. What I would rather have is

IRepository myRepository = new ConcreteRepositoryImpl();

so that I am using the interface.

 avatar

Tim Tonnesen said on 09 Aug 2009 at 1:27 PM

Another pain point of var overuse is Find Usages in Resharper.

Say your repository method above returns IEnumerable<Product> and you want to R# usages of type Product. Well, it won't list "products" in "var products..." as a usage of type Product.

Leave a Comment

Please join the discussion and share your thoughts.