When to use Type Inference


Occasionally the debate will come as to when it’s OK to use type inference in order to declare a variable.  There appear to be three groups in this debate.

  1. Whenever it’s possible
  2. Only when it’s absolutely clear what the type is
  3. Never, type inference is evil

I fall into camp #1 and here are my reasons

  • It does not reduce type safety.  This doesn’t allow for any late binding, type unsafe functions or the like.  It simply lets the compiler chose the type for you.
  • It will actually increase type safety in your code.  The best example of this is the foreach statement on non-generic IEnumerable instances.  These foreach statements are all technically unsafe because the compiler must do a cast of the Current member under the hood.  This declaration looks no different than the type safe generic version of IEnumerable.  Using var will force you to write an explicit cast.  

foreach (SomeType cur in col)

foreach ( var cur in col.Cast<SomeType>())

  • Maintains the principles of DRY.  This is mostly true for cases where you have an explicit constructor on the RHS.
  • For some types, this is a requirement in order to use the type (anonymous types for instance).  I’m a big fan of consistency and since I must have some instances use type inference, I’d like to use them everywhere. 
  • Makes refactoring easier.  I re-factor, a lot.  I constantly split up or rename types.  Often in such a way that refactoring tools don’t fixup all of the problems.  With var declarations I don’t have to worry because they just properly infer their new type and happily chug along.  For explicit type cases I have to manually update all of the type names. 
  • Less typing with no loss of functionality.

The best argument I’ve heard against type inference is that it reduces readability since you can’t look at a variable and know it’s type.  True, but just hover over the declaration and the IDE will display the type.  Yes this is not possible with a non-IDE editor but how often do you use one?

Comments (27)

  1. Skurmedel says:

    Actually you don’t have the IDE readily available when you’re merging things from your source control. Just something to think about.

  2. jtenos says:

    I’d have to be on the opposite side of the discussion.  When I’m dealing with several layers of inheritance on my objects, I like to know exactly what type I’m working with at all times, and I want the compiler to yell at me if I try to change types of things without telling it.

    This is especially important to me if I have any "new" methods (as opposed to override) – this doesn’t come up often, but suppose:

    class Foo { public void DoSomething(){} }

    class Bar : Foo { public new void DoSomething(){} }

    var v = new Bar();

    Foo f = new Bar();

    v.DoSomething();

    f.DoSomething();

    v thinks that it’s a Bar, not a Foo, so it calls the Bar.DoSomething method.  What if I really want it to be a Foo?

    But that’s just my opinion – maybe I’m just afraid of change…I will say that anonymous types are a wonderful thing, and since that kind of goes hand-in-hand with type inference, I can’t be completely against it…

  3. Tom Kirby-Green says:

    Personally I think using ‘var’ outside of scenarios involving anonymous types makes it very hard to grep large codebases for type usage. It makes it almost impossible to do a impact-analysis when trying to figure of the risk involved in swapping one type for another. I can’t ‘hover my mouse’ over a 7 million line code base.

  4. @Tom,

    For any kind of type swapping in a large project, grep is almost always insufficiennt because it’s a text vs. symbol search.  In these cases I prefer to rely on the IDE to get back information on type usage.  

  5. John Baughman says:

    @jtenos: Then do this -> var v = new Foo().

    v will now be a Foo. Computers only do what we tell them to do…

    @Tom: 7 million lines? I hope there is also some documentation! 😉 I still don’t see the issue with swapping types. Swapping types can be a nightmare anyway. What if the type you currently have declared has the method ToString and the one you swap it with doesn’t? To var or not to var isn’t going to matter in this case, your code is broken. Yes, var works BEST in the IDE, but it can work otherwise, just do it judiciously. And always document.

  6. Joe Enos says:

    @John:

    Obviously that was a very simplified scenario.  I want an actual object of type Bar, but declared as a Foo – to get the Foo’s version of DoSomething(), but the Bar’s version of everything else (assuming there are virtual members as well).

  7. Bart says:

    This one here is in camp 2, as explained on http://community.bartdesmet.net/blogs/bart/archive/2008/08/23/appropriate-use-of-local-variable-type-inference.aspx. There are a few subleties where type inference can be considered harmful or where it cannot be used. But most importanty, I like to optimize my code for reading it and hinting at the type of a variable when it’s not directly clear from the context can help a lot.

    -Bart

  8. GPS says:

    I’m definately in camp 2.  I’ve spent days looking at ASP (JavaScript and VBScript) and VB code which use variants for every variable.  I do understand that var in C# is a ton safer than variant, however, the do have one problem in common.  You have to infer what the code is doing and keep in mind what all of the variables represent.  I’m doing corporate development with a large offshore contingent of programmers.  I’d rather make sure those reading my code know exactly what I mean than let them assume any part of it.  Even my architecture team agrees that var isn’t something to use unless absolutely necessary.  

    I would love to hear from the C# team at M$ to see what their take on var is.

  9. Ferdinand Swaters says:

    The var keyword is kinda convenient for keying in the program, but it would be nice if the IDE just translated it to the proper type. Neigh, some sayeth, that cannot be done since we have anonymous types!  

    And they are wrong. Yes we do have anonymous types and yes we do need var to store them, but that is because the type is anonymous, something that no-one wanted in the first place! We needed a type that can be defined ‘on the fly’, and anonymous type does that nicely. But we never wanted it to be anonymous, that is an inconvenience brought upon us because there is no syntax to tell the compiler it’s name and access.

    I think it is sad that a class that has a great virtue, being defined on the spot, is named after it’s worst aspect, that it is anonymous.

  10. shirvan says:

    OK, there is always tradeoffs, Everywhere we want to use something in code we must have reasons for it, there aren’t necessary reasons to push me for using type inference everywhere in my code, and here are drawbacks:

    yes of course, var is type safe but what is our gain in using it everywhere?

    compiler acts like this: when sees the var keyword it tries to find the type of variable based on the value assigned to it, this means that we can’t assign a value that compiler can’t determine it’s type, and this results to:

    We can’t use var when initializing a variable to null, cause compiler can’t determine it’s type.

    OK lets see another case, suppose we have the following line of code:

    var amount = 13;

    Now what is amount? int16, int32 or int64?

    or another example:

    var tax = taxCalculator.GetTax(amount);

    Now what is the type of tax???

    These are really confusing and it’s not a good practice to use type inference in these situations.

    Or something like this:

    var firstName = "shirvan";

    What is our gain using var instead of string??? i think nothing.

    In DRY case I’m agree that repeating is unnecessary in variable declaration and in my opinion the right side type declaration is unnecessary and redundant, but to get rid of this redundancy c# compiler should take the responsibility and enables this feature(maybe in future releases) instead of using var and sacrificing readability.

    The var keyword is very cool feature in c# 3.0, I’m also a big fan of Intelligent laziness and less typing but i think it’s not applicable here and we shouldn’t use type inference everywhere in our code, the right place to use it is when dealing with anonymous types or a collection of anonymous types.

    Shirvan

  11. Joren says:

    We declare variables with type included for two reasons:

    1. We use a statically typed language. We need to tell the compiler what the type of the variable should be to get the desired functionality.

    2. We want to tell a human reader what the type of the variable is.

    When type inference fails you can’t use var, so let us assume it doesn’t.

    With this however, the first problem is not yet solved. As jtenos showed, there are still cases where the type of a variable should not be what type inference thinks it should be.

    In this case, we can not correctly use var, so we shouldn’t.

    Now let us assume that type inference not only does not fail, but it also gives us the right answer (i.e. doesn’t give a false positive).

    Now the first problem is solved, but the second might still be there.

    I use var if and only if there is no need to tell the reader what the type is. I see only a few cases in which this is true:

    1. It is clear from the variable assignment how the variable is to be used; the exact type doesn’t matter.

    2. It is clear from the variable assignment what the exact type of the variable is.

    3. Some third party (IDE, you sitting next to the him, etc.) is guaranteed to be always available and present to inform the reader what the type of the variable is.

    If there IS a need to tell the reader what the type of a variable is, you should not use var.

    I think being part of group 1 is a VERY bad idea. ‘Whenever it’s possible’ doesn’t even guarantee that the compiler knows the correct type (it knows a type it can compile the code with, but as jtenos showed that type is not necessarily the correct type), let alone the reader.

    I think group 3 is ridiculous. (Also seems very much like a straw man to me.) If problem 2 is solved somehow and type inference manages to solve problem 1, then there is no problem.

    I think group 2 is too strict (might also a be a straw man), but close to the right idea.

    I hereby propose two new groups to replace groups 2 and 3.

    Group 4 says ‘never, because I don’t believe problem 2 can ever be solved without explicitly giving the type’. I think this is perfectly reasonable, but I don’t think the premise is true.

    Group 5 says ‘only when type inference gives the desired type AND problem 2 is somehow solved’

  12. @Joren

    Unfortunately #3 is not a straw man and is very real.  The original intent of this post was to be a FAQ of sorts for people in the #3 camp to hopefully squash out some of the incorrect assumptions I came across in various discussions.  

    I don’t buy the argument that Type Infereence gave the incorrect type in JTenos’ scenario.  It worked to the specification 100% and correctly inferred the exact type of the expression.  It’s also completely evident from the expression what type should be inferred.  There is no ambiguity in the type.

    The user is bitten in this scenario becase they attempted to use a method defined with "new".  When calling a method defined with "new" the type of the reference is of upmost importance.  The issue of what reference should be use exists with or without type inference being in the picture.  You could argue that explicit types make this much clearer but in this case the type is staring you in the face so there should be no ambiguity.  

    IMHO you should avoid "new" with or without type inference.  It is an evil feature.  

    I’m having trouble following your definition for Group 4 and Group 5.  You mention problem #2.  Unfortunately there are now (just between your comment and my post) 3 numbered lists.  Can you be more specific on what problem #2 refers to?

  13. Joren says:

    I meant that the inferred type was incorrect in that it does not offer the desired functionality. It is still a reasonable choice; there is no way for the compiler to know the programmer wants different functionality.

    Every time I refer to problem #2 I mean

    ‘2. We want to tell a human reader what the type of the variable is.’

    Sorry for being unclear.

  14. Rob Grainger says:

    @Shirvan,

    While I’d agree that…

     var str = "hello";

    is not much better than…

     string str = "hello";

    that’s a trivial example. What about..

     System.Collections.Generic.IList<

       System.Collections.Generic.IList<

         MyPair<int, double>>> pairListLists =

           new System.Collections.Generic.IList<

             System.Collections.Generic.IList<

               MyPair<int, double>>>();

    Having to type and/or read that type signature once is a godsend and a clear violation of the DRY principle. If they are updated inconsistently, can lead to errors (OK, generally compile-time, but still a pain).

    Rob

  15. Nick says:

    It’s disgusting.  If you know what type you’re going to be using then it’s just laziness.  If you don’t know what type you’re going to use then you have far deeper problems and should really reevaluate your design and implementation.

    ‘var’ should be left for Javascript.  It doesn’t reduce type-safety, but there’s absolutely no need to use it, it doesn’t benefit you in any way except that the word ‘var’ may be shorter than your type name.

    Readability suffers, later developers suffer (trying to match up code with ‘var’s all through it with a well written design document is hell, trust me).

    It’s syntactic sugar for the lazy people or for very small scale test projects only.

  16. Nick says:

    Except in situations with anonymous types… woops, forgot that one! 🙂

    Anonymous anything can be the devil when used too often – they’re excellent solutions to specific problems and shouldn’t be used just because they can be.

  17. shirvan says:

    @Rob

    This article proposed to use type inference everywhere it’s possible, I’m not agree with that and i don’t consider it a good practice.

    About your example, first of all it seems too long because of the generic namespace in front of IList, despite of that i still favor readability over less typing.

    I’m stated in my previous comment about DRY, i think it’s a compiler task to enable this feature for us and still not loosing readability, maybe something like this:

    MyType x= new(param);

    but now I’m not agree to sacrifice readability in exchange of less typing.

    Shirvan

  18. Harper Shelby says:

    I’ve got to agree that the 3 choices are not all of the camps, though I suppose I could be a camp of  one ;). My opinion of the 3 positions listed:

    #1 – Whenever possible, to me, is the justification for lazy typing and, at times, sloppy thinking. IMHO, a programmer should have a pretty darn good idea in mind exactly what the variables in the code are. Using var because you don’t want to think hard about the code is just a *bad* idea. While an iDE can tell you about a variable, having real knowledge of what your code is doing is critical to developing software, as opposed to slinging code.

    #2 – This one is the *most* confusing to me. If it’s so blindingly obvious what the type is, why not just *use* the type name? Using var is pointless at best, and risks obscuring the blinding obviousness at best.

    #3 – While there’s a little part of me that almost lands in this camp (I think it’s the C++ roots showing), I do know that LINQ queries and other similar situations can result in compiler-generated anonymous types that are *not* known in advance, and so there are situations where var is not only useful, but necessary.

    So my position #4 is this: use var only when you must, or when the type returned is knowable, but not readily obvious. Again, the prime example is LINQ queries – while they don’t always return anonymous types, at times the type they *do* return is harder to determine than to use properly (though I lean towards full and proper type declaration even then).

  19. @Harper,Nick

    I disagree with the assertion that using "var" is sloppy.  There’s nothing sloppy about letting the compiler choose the type for me.  I made a concious choice of type when I created the API, there is no reason for me to repeat it everywhere in my code.  

    As a counter argument, how do you feel about generic types on static methods?  As long as a static method takes enough parameters to satisfy all type requirements there is no need to explicitly specify them.  For instances

    static void Func1<T>(T p1);

    Func1(42);

    Do you consider this sloppy or lazy?  

    To the readability argument.  I find that type inference makes my code more readable, not less.  I think people are unnecessarily focussing on what exactly the type is.  I counter back why does the type matter?  You can look at the code and be assured that it compiles since var does not reduce type safety.  Is it extremely important to know the exact type of every function?  Wouldn’t it be better to focus on the algorithm?  If you ever need to know the type then just look at the function or hover over the variable.  Either will do.  

    I’m also reluctant to use the term lazy.  In CS, I find the term "lazy" is associated with a piece of code which allows for more errors or bad conditions.  Adding var does neither.  I prefer the term "concise" or "efficient."

  20. David Nelson says:

    I am in the #2 camp. In cases where var simply eliminates redundancy in C# declarations, I have no problem with it. And in cases involving anonymous types, you have no choice. But outside of those two cases, var eases writability at the expense of readability. Since all code is read many more times than it is written, optimizing for readability is the more important factor, and var doesn’t help me do that.

  21. David Nelson says:

    @Jared,

    I didn’t see your comment before I posted mine. To answer your questions:

    1. Inferred generic type parameters don’t bother me because generic methods by definition don’t need to know the actual type in order to function correctly. A generic method which changes its behavior based on its input type is poorly written.

    2. It is not always extremely important to know the exact type of every function (or variable or property). However, sometimes it IS important. The problem is, you almost never know when those times will be. It is only when you or some other developer comes along later trying to read the code that you realize that you need to know the types involved. When you are trying to do code reviews or understand code that you have not seen before, seeing the types involved goes a long toward being able to quickly assimilate the code. Saving a few characters in the variable declaration is just not worth the loss of that information to the reader.

  22. Nick says:

    @David

    I agree with number 1 100%.  Number 2 I also agree with (about 98%), but I would go so far as to say the type ALWAYS matters.  C# is so heavily steeped in Object Oriented Programming that types (classes, structs, interfaces etc.) are all that is ever used.

    @Harper

    The generic situation is odd – I have never personally had the need for a static, generically typed function, but I would NEVER write it that way you did.

       Func2<int>(42);

    Otherwise, someone reading that has no frigging idea it’s a generic function!  It may be perfect for what someone wants to do but they think it only takes integers or something, I don’t know, some programmers aren’t too smart.

    I would always explicitly state what type is being used (in fact, I didn’t even know it would let you compile your way).

    ‘var’ is not only sloppy, it’s lazy and completely unnecessary in 99.9% of situations.  I don’t use LINQ so I haven’t needed to use ‘var’ ever, but from what I’ve read you can’t do that situation without ‘var’ (at least without sacrificing strong typing).

    How long does it take to type out a type name?  Intellisense cuts that time to about two or three letters worth of typing plus a tab.  But really, I don’t care what you do as long as I never have to trawl through your code wondering what the hell is going on.

  23. Dear Rob Grainger,

    What about using a using statement instead of giving a dirty example in favour of using var.

    Your example is much more readable like below:

    IList<IList<MyPair<int, double>>> pairListLists = new IList<IList<MyPair<int, double>>>();

    The var keyword was mainly introduced for use with Linq and anonymous types. So I use the var keyword when it is absolutely needed or when I can clearly see which type is meant.

    Your code should be readable and understandable from outside an IDE, such as a website or a print. Var makes that very difficult or somethimes impossible!

  24. Tr3v says:

    For my two cents, if you feel strongly against the var keyword and you are not using anonymous types you can still do linq queries and write the code as follows:

    IEnumerable<MyClass> sortedMyClasses =

    from myClass in myClasses

    orderby myClass.Property

    select myClass;

    which is all var would get translated to anyway.

  25. Paul Stovell says:

    I’m with Jared 100% – use type inference whenever possible.

    What’s nice is that along with "as", it can be used consistently at all times. For example:

    var monthsInYear = 12;

    var foo = null as IFoo;

    var foo = new Bar() as IFoo;

    Which solves the second comment above about the use of "new" shadowing (though I agree that the real WTF here is the use of "new", not the use of "var").

    Now I code happily on "Enterprise" projects using var 100% of the time, and yet the sky has not fallen 🙂

  26. Cheap shot says:

    I’m completely with Nick.

    Except he forgot to mention the namespace keyword.

    If you’re not typing out the entire class name each and everytime then you can’t be sure what you’re referencing.

    The namespace keyword is just syntactic sugar and if you’re using it then you’re lazy.