Click here to Skip to main content
15,888,980 members
Articles / Programming Languages / C# 4.0

Best Practices on Using Implicitly Typed (i.e. var ) and Explicitly Typed Variables

Rate me:
Please Sign up or sign in to vote.
2.68/5 (14 votes)
4 Nov 2009CPOL1 min read 82.5K   5   60
Best practise using var

Introduction

Leveraging the type inference is wonderful when writing code. With the arrival of ‘var’ in C# 3.0, it now allows a developer to write more relaxed code.

int i = 2 can now be written as var i = 2, without having to worry about the overhead for boxing/un-boxing.

The compiler infers the type indicated by ‘var’ from the expression used to initialize the variable, and the IL code contains the inferred type. However, it is not always the best thing to use var. While using ‘var’ can help developers to avoid all the type declarations for local variables, it has an impact on code readability. Consider invoking an overloaded method, which differs in the parameter type. If the method is invoked with parameters declared as ‘var’, it makes the code complex to understand.

Consider the following snippet:

C#
private int GetUserInput()
{
    Random r = new Random(1);
    return r.Next();
}

private int Add(int numberOne, int numberTwo)
{
    return numberOne + numberTwo;
}
private float Add(float numberOne, float numberTwo)
{
    return Convert.ToInt32(numberOne + numberTwo);
}

private void InvokeAdd()
{
    var numberOne = GetUserInput();
    var numberTwo = GetUserInput();
    //...
    var addedNumber = Add(numberOne, numberTwo); //version of ‘Add’ method is not evident
}

Which version of ‘Add’ method is invoked is not evident at the first glance, in the above snippet.
Although the best practices for using ‘var’ cannot be made generic but a little guidance can help in making a conscious choice. Below are a few thoughts on when to use or not to use ‘var’.

  1. Do use ‘var’ to:
    1. Refer anonymous types, e.g.
      C#
      var anonymousType = new { Name = "Dilbert" };
    2. Refer query expressions, e.g.
      C#
      var queryExpression = from c in customers where c.Name == "Dilbert" select c;
    3. Refer complex generic types, e.g.
      C#
      var searchList = new Dictionary<string>();
  2. Do not use ‘var’ to:
    1. Refer known types, e.g.

      C#
      var customer = new Customer(); //Do not use 
      var numberList = new int[] { 1, 2, 3, 4, 5 }; //Do not use.
    2. Refer constants, e.g.

      C#
      var i = 5; //Do not use
    3. Refer simple expression assignments, e.g.

      C#
      var count = customers.Count();//Do not use
      var customerName = customer.Name;//Do not use
    4. Refer variables where types cannot be inferred or where inferred type is not what is intended, e.g.

      C#
      IList<customer> customers = new List<customer />(); //Do not use

      Consider code readability and maintainability while making a choice between ‘var’ and explicit type.

History

  • 4th November, 2009: Initial post

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Unknown
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralMy vote of 1 Pin
Björn Friedrich14-Jan-11 5:05
Björn Friedrich14-Jan-11 5:05 
GeneralMy vote of 1 Pin
Richard Deeming12-Nov-09 9:00
mveRichard Deeming12-Nov-09 9:00 
General[My vote of 1] Мethodically, socially and morally incorrect Pin
Sergey Alexandrovich Kryukov9-Nov-09 6:51
mvaSergey Alexandrovich Kryukov9-Nov-09 6:51 
GeneralSuch an overreaction... Pin
CurtainDog9-Nov-09 19:45
CurtainDog9-Nov-09 19:45 
GeneralRe: Such an overreaction... Pin
Sergey Alexandrovich Kryukov10-Nov-09 5:43
mvaSergey Alexandrovich Kryukov10-Nov-09 5:43 
GeneralMy vote of 1 Pin
brian_agnes9-Nov-09 6:04
brian_agnes9-Nov-09 6:04 
GeneralShould be based on facts and reasoning Pin
Sergey Alexandrovich Kryukov9-Nov-09 6:36
mvaSergey Alexandrovich Kryukov9-Nov-09 6:36 
GeneralMy vote of 2 Pin
Ben Robbins8-Nov-09 21:48
Ben Robbins8-Nov-09 21:48 
GeneralRe: My vote of 2 [modified] Pin
ATANU.PODDER8-Nov-09 23:15
ATANU.PODDER8-Nov-09 23:15 
GeneralMy vote of 2 Pin
dequadin7-Nov-09 6:52
dequadin7-Nov-09 6:52 
GeneralRe: My vote of 2 Pin
ATANU.PODDER8-Nov-09 23:27
ATANU.PODDER8-Nov-09 23:27 
GeneralI understand the boxing reference Pin
Member 36807856-Nov-09 5:09
Member 36807856-Nov-09 5:09 
GeneralRe: I understand the boxing reference Pin
dberindei8-Nov-09 22:24
dberindei8-Nov-09 22:24 
GeneralRe: I understand the boxing reference Pin
Member 36807859-Nov-09 6:36
Member 36807859-Nov-09 6:36 
GeneralRe: I understand the boxing reference Pin
dberindei9-Nov-09 21:23
dberindei9-Nov-09 21:23 
GeneralRe: I understand the boxing reference [modified] Pin
Member 368078511-Nov-09 7:45
Member 368078511-Nov-09 7:45 
dberindei wrote:
This is precisely not what the var keyword does... try if for yourself, replace Object with var and you'll see that the code no longer compiles.


I never claimed that "Object" and "var" were equivalent at a text replacement level. I made the point that either one could be used, in some sense at least, as a typing shortcut to avoid tediously re-entering the same type name within a single declaration. This does not necessarily require a bunch of typecasts, as you claimed. I can make my own methods take Objects, and then no casting is required. You probably think this is a crappy approach, and I agree. But some of the .NET Framework methods take this very approach- hence my mention of ArrayList.

dberindei wrote:

Microsoft did care about performance from the beginning, you could always use straight arrays instead of ArrayList. In fact that's how most of the early APIs work.


Sure, I could have used arrays, if I was willing to allocate the storage myself, worry about sizing it, etc. Most programmers justifiably will not want to do this, and use of ArrayList was thus very pervasive in the early days on .NET. If you don't believe that, I'm sorry, but you've got your head in the sand.

Beyond that, I think your line of commentary exhibits a bit of historical revisionism. Around the time they started hyping Vista and WPF, Microsoft started pushing .NET as a high-performance technology. WPF is supposed to be fast, and it's intimately coupled with .NET 3.0. That means that, unlike prior versions, .NET 3.0 couldn't aim at the (low) performance of Java. Now, Microsoft was claiming that it was fast in an overall sense.

There was a transformation in thinking that happened, and you can deny it, but things like ArrayList still exist and they betray the fact that .NET was originally intended much more as a "toy" or "boutique" technology than what it's (unfortunately) become today, i.e. the answer to Everything You'll Ever Actually Need To Write (TM) Brought to You By Microsoft.

Of course, the value of making things slower for Microsoft is that existing hardware will become inadequate, and will need to be replaced. This hardware will be purchased with a brand new copy of Windows already paid for.

Also, Microsoft is only too happy that more and more code will be written in C#, which cannot even execute without their continued legal permission. Code written in .NET basically has its real ownership shared with Microsoft. If Microsoft decides it shouldn't compile, it won't. They certainly don't mind that, and if lying about .NET performance is the price that must be paid to this end, they apparently have no scruples about that.


dberindei wrote:
I don't know what you mean with "moving polymorphic operations forward-in-time", but generics don't do this


"Generics" in the overall sense (e.g. C++ and Java) definitely do move things forward in time. If you make a C++ template, for example, and then use it for (say) type "int," then code gets generated at compile-time with "int" put in place of your type parameter name. So, by the time the code actually runs, any operations related to dealing with multiple types are gone. The executing code deals with data exactly as if you'd coded an entire library around "int," even though it was written around some hypothetical type probably named something like T or U. Compared to a polymorphic approach to the same problem (which almost always exists, and ends up checking types and dereferencing a Vtable at runtime) operations are indeed moved forward in time, i.e. to compilation.

I have researched C# "generics" a bit, and they are not implemented this way. C# "generics" are inherent to IL and thus survive the build process. So you are correct in that sense (although I think I could come up with some examples of type checking that do "get moved forward in time" by C# generics).

However, I should also point out that I find this design to be asinine. IL has basically turned into Yet Another High-Level Language. It is no longer an assembly-like language like UCSD p-Code or Java bytecodes, both of which were in fact actually implemented directly in hardware at one point. IL has become just another bloated layer standing between the .NET programmer and the hardware.

Beyond that, in C++, I am allowed to take hypothetical types T and U and write code that attempts to do basically anything with them, e.g.

template <class T >
void()
{
T t1, t2;
//etc... Eventually, we try this:
t1+=t2;
}

I have blatantly assumed that "T" supports addition, with no basis in fact. But in C++, this compiles without error, unless and until someone uses the template for a type that really doesn't support addition.

To my mind, this is a key part of the power of C++ templates, and it's completely missing in .NET. C# generics, for example, simply fail at compile time if you make assumptions like I did in my C++ example.

modified on Saturday, November 14, 2009 10:16 AM

GeneralRe: I understand the boxing reference Pin
dberindei11-Nov-09 23:04
dberindei11-Nov-09 23:04 
GeneralRe: I understand the boxing reference Pin
Indrora23-Nov-09 16:10
Indrora23-Nov-09 16:10 
GeneralRe: I understand the boxing reference Pin
dberindei23-Nov-09 21:42
dberindei23-Nov-09 21:42 
GeneralRe: I understand the boxing reference Pin
Indrora4-Dec-09 16:12
Indrora4-Dec-09 16:12 
GeneralRe: I understand the boxing reference Pin
dberindei9-Dec-09 2:17
dberindei9-Dec-09 2:17 
GeneralWhy comparing "object" with "var"? Pin
Sergey Alexandrovich Kryukov9-Nov-09 6:33
mvaSergey Alexandrovich Kryukov9-Nov-09 6:33 
GeneralRe: Why comparing "object" with "var"? Pin
Member 368078511-Nov-09 9:39
Member 368078511-Nov-09 9:39 
GeneralRe: Why comparing "object" with "var"? Pin
Sergey Alexandrovich Kryukov11-Nov-09 12:14
mvaSergey Alexandrovich Kryukov11-Nov-09 12:14 
GeneralMy vote of 2 Pin
Utwig6-Nov-09 2:58
Utwig6-Nov-09 2:58 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.