Uses and misuses of implicit typing


One of the most controversial features we’ve ever added was implicitly typed local variables, aka “var”. Even now, years later, I still see articles debating the pros and cons of the feature. I’m often asked what my opinion is, so here you go.

Let’s first establish what the purpose of code is in the first place. For this article, the purpose of code is to create value by solving a business problem.

Now, sure, that’s not the purpose of all code. The purpose of the assembler I wrote for my CS 242 assignment all those years ago was not to solve any business problem; rather, its purpose was to teach me how assemblers work; it was pedagogic code. The purpose of the code I write to solve Project Euler problems is not to solve any business problem; it’s for my own enjoyment. I’m sure there are people who write code just for the aesthetic experience, as an art form. There are lots of reasons to write code, but for the sake of this article I’m going to make the reasonable assumption that people who want to know whether they should use “var” or not are asking in their capacity as professional programmers working on complex business problems on large teams.

Note that by “business” problems I don’t necessarily mean accounting problems; if analyzing the human genome in exchange for National Science Foundation grant money is your business, then writing software to recognize strings in a sequence is solving a business problem. If making a fun video game, giving it away for free and selling ads around it is your business, then making the aliens blow up convincingly is solving a business problem. And so on. I’m not putting any limits here on what sort of software solves business problems, or what the business model is.

Second, let’s establish what decision we’re talking about here. The decision we are talking about is whether it is better to write a local variable declaration as:

TheType theVariable = theInitializer;

or

var theVariable = theInitializer;

where “TheType” is the compile-time type of theInitializer. That is, I am interested in the question of whether to use “var” in scenarios where doing so does not introduce a semantic change. I am explicitly not interested in the question of whether

IFoo myFoo = new FooStruct();

is better or worse than

var myFoo = new FooStruct();

because those two statements do different things, so it is not a fair comparison. Similarly I am not interested in discussing bizarre and unlikely corner cases like “what if there is a struct named var in scope?” and so on.

In this same vein, I’m interested in discussing the pros and cons when there is a choice. If you have already decided to use anonymous types then the choice of whether to use implicit typing has already been made:

var query = from c in customers select new {c.Name, c.Age};

The question of whether it is better to use nominal or anonymous types is a separate discussion; if you’ve decided that anonymous types are worthwhile then you are almost certainly going to be using “var” because there is no good alternative.

Given that the overarching purpose is assumed to be solving business problems, what makes good code? Obviously that’s a huge topic but three relevant factors come to mind. Good code:

  • works correctly according to its specification to actually solve the stated problem
  • communicates its meaning to the reader who needs to understand its operation
  • allows for relatively low-cost modification to solve new problems as the business environment changes.

In evaluating whether or not to use “var” we can dismiss the first concern; I’m only interested in pros and cons of cases where using var does not change the meaning of a program, only its textual representation. If we change the text without changing its semantics then by definition we have not changed its correctness. Similarly, using or not using “var” does not change other observable characteristics of the program, such as its performance. The question of whether or not to use “var” hinges upon its effect on the human readers and maintainers of the code, not on its effect upon the compiled artefact.

What then is the effect of this abstraction on the reader of the code?

All code is of course an abstraction; that’s the whole reason why we have high-level languages rather than getting out our voltmeters and programming at the circuit level. Code abstractions necessarily emphasize some aspects of the solution while “abstracting away” other aspects. A good abstraction hides what is irrelevant and makes salient what is important. You might know that on x86 chips C# code will typically put the value returned by a method in EAX and typically put the “this” reference in ECX, but you don’t need to know any of that to write C# programs; that fact has been abstracted away completely.

It is clearly not the case that more information in the code is always better. Consider that query I referred to earlier. What is easier to understand, that query, or to choose to use a nominal type and no query comprehension:

IEnumerable<NameAndAge> query = Enumerable.Select<Customers, NameAndAge>(customers, NameAndAgeExtractor);

along with the implementations of the NameAndAge class, and the NameAndAgeExtractor method? Clearly the query syntax is much more abstract and hides a lot of irrelevant or redundant information, while emphasizing what we wish to be the salient details: that we are creating a query which selects the name and age of a table of customers. The query emphasizes the business purpose of the code; the expansion of the query emphasizes the mechanisms used to implement that purpose.

The question then of whether “var” makes code better or worse for the reader comes down to two linked questions:

1) is ensuring salience of the variable’s type important to the understanding of the code? and,
2) if yes, is stating the type in the declaration necessary to ensure salience?

Let’s consider the first question first. Under what circumstances is it necessary for a variable’s type to be clearly understood when reading the code? Only when the mechanism of the code — the “how it works” — is more important to the reader than the semantics — the “what its for”.

In a high-level language used to solve business problems, I like the mechanisms to be abstracted away and the salient features of the code to be the business domain logic. That’s not always the case of course; sometimes you really do care that this thing is a uint, it has got to be a uint, we are taking advantage of the fact that it is a uint, and if we turned it into a ulong or a short, or whatever, then the mechanism would break.

For example, suppose you did something like this:

var distributionLists = MyEmailStore.Contacts(ContactKind.DistributionList);

Suppose the elided type is DataTable. Is it important to the reader to know that this is a DataTable? That’s the key question. Maybe it is. Maybe the correctness and understandability of the rest of the method depends completely on the reader understanding that distributionLists is a DataTable, and not a List<Contact> or an IQueryable<Contact> or something else.

But hopefully it is not. Hopefully the rest of the method is perfectly understandable with only the semantic understanding, that distributionLists represents a collection of distribution lists fetched from a storage containing email contacts.

Now, to the crowd who says that of course it is better to always know the type, because knowing the type is important for the reader, I would ask a pointed question. Consider this code:

decimal rate = 0.0525m;
decimal principal = 200000.00m;
decimal annualFees = 100.00m;
decimal closingCosts = 1000.00m;
decimal firstPayment = principal * (rate / 12) + annualFees / 12 + closingCosts;

Let’s suppose that you believe that it is important for all the types to be stated so that the code is more understandable. Why then is it not important for the types of all those subexpressions to be stated? There are at least four subexpressions in that last statement where the types are not stated. If it is important for the reader to know that ‘rate’ is of type decimal, then why is it not also important for them to know that (rate / 12) is of type decimal, and not, say, int or double?

The simple fact is that the compiler does huge amounts of type analysis on your behalf already, types which never appear in the source code, because for the most part those types would be distracting noise rather than helpful information. Sometimes the declared type of a variable is distracting noise too.

Now consider the second question. Suppose for the sake of argument it is necessary for the reader to understand the storage type. Is it necessary to state it? Often it is not:

var prices = new Dictionary<string, List<decimal>>();

It might be necessary for the reader to understand that prices is a dictionary mapping strings to lists of decimals, but that does not mean that you have to say

Dictionary<string, List<decimal>> prices = new Dictionary<string, List<decimal>>();

Clearly use of “var” does not preclude that understanding.

So far I’ve been talking about reading code. What about maintaining code? Again, var can sometimes hurt maintainability and sometimes help it. I have many times written code something like:

var attributes = ParseAttributeList();
foreach(var attribute in attributes)
{
    if (attribute.ShortName == “Obsolete”) …

Now suppose I, maintaining this code, change ParseAttributeList to return a ReadOnlyCollection<AttributeSyntax> instead of List<AttributeSyntax>. With “var” I don’t have to change anything else; all the code that used to work still works. Using implicitly typed variables helps make refactorings that do not change semantics succeed with minimal edits. (And if refactoring changes semantics, then you’ll have to edit the code’s consumers regardless of whether you used var or not.)

Sometimes critics of implicitly typed locals come up with elaborate scenarios in which it allegedly becomes difficult to understand and maintain code:

var square = new Shape();
var round = new Hole();
… hundreds of lines later …
bool b = CanIPutThisPegInThisHole(square, round); // Works!

Which then later gets “refactored” to:

var square = new BandLeader(“Lawrence Welk”);
var round = new Ammunition();
… hundreds of lines later …
bool b = CanIPutThisPegInThisHole(square, round); // Fails!

In practice these sorts of contrived situations do not arise often, and the problem is actually more due to the bad naming conventions and unlikely mixtures of business domains than the lack of explicit typing.

Summing up, my advice is:

  • Use var when you have to; when you are using anonymous types.
  • Use var when the type of the declaration is obvious from the initializer, especially if it is an object creation. This eliminates redundancy.
  • Consider using var if the code emphasizes the semantic “business purpose” of the variable and downplays the “mechanical” details of its storage.
  • Use explicit types if doing so is necessary for the code to be correctly understood and maintained.
  • Use descriptive variable names regardless of whether you use “var”. Variable names should represent the semantics of the variable, not details of its storage; “decimalRate” is bad; “interestRate” is good.
Comments (54)

  1. David V. Corbin [MVP] says:

    Eric, I like your analysis, but believe you left out one case (at least explicitly) that has been important in actual projects I work on. That is when you want the code to BREAK in the event of a type change.

    Consider a control system. Many elements have On() and Off() methods. there are many cases where there is no relationship between the types (i.e. no common base classes or interfaces), there is only the similarity that both have methods with those signatures.

    Now I write code:

    var thing = SomeFactory.GetThing()  // Returns something that is safe to turn off…

    thing.Off().

    Then later a change is made to the Factory and that method now returns something completely different, which happens to have severe consequences if it is arbitrarily turned off [having such a design is debatable for many reasons – but they are outside the defined scope of your post].

    By using var, the previous code will compile without compliant. Even though the return type may have changed from "ReadingLamp" to "LifeSupportSystem".

    I believe (based on my experiences as a "traveling consultant") that there are more time when there is the possibility of an "unintended side-effect" caused by a change in the type than there are times where the change in type has no bearing on the code that consumes it. As a result, I very rarely use var. Even when the return type is obvious (such as the LHS of a "new"), I find it easier to be consistent.

  2. Anthony P says:

    I'll deal with it if the team I'm on dictates it, but as for my personal preference, you'll have to pry explicitness from my cold dead hands. Within reason, of course, as I concede the point on anonymous typing, even enumerable query results in general, and (of course) sub-expressions.

    While I am rationally aware that the static typing is the same as always, it just reminds my irrational brain too much of weak typing in scripting languages and VB and makes me cringe.

  3. Patrick Dewane says:

    @David – in your example I would have to imagine your factory is responsible for creating similar objects given the business domain. If your factory could return a "ReadingLamp" or "LifeSupportSystem", then I would assume your factory is called "ThingsThatTurnOffFactory" and might involve revisiting a design decision.

  4. Olivier says:

    The fact that the type should be spelt out only if needed, seems more obvious to me when I consider that it is possible to use a cast as a type annotation. Compare:

    TheType theVariable = theInitializer;

    var theVariable = (TheType)theInitializer;

    With var, all declarations become nicely lined up, *and* optional explicit typing is still possible.

    I use var everywhere (btw C# also needs "val" from Scala).

  5. David Nelson says:

    Easily the most clear, succinct, and relevant analysis of the pros and cons of var I have ever read.

    @David V. Corbin,

    That is exactly the kind of contrived scenario that Eric was referring to as being due to bad design rather than the use of implicit typing. If you really have a method that may realistically change from returning a lamp to returning a life support system, you have MUCH bigger problems than whether or not to use var.

  6. Alex Stockton says:

    Despite being very used to explicitly typed locals prior to the introduction of var, implicitly typed locals are now the default for me.

    Type mechanisms are rarely so important to the business problem being solved that the type needs to be immediately visible in the code.

    Even when a type is important to understanding, most code is viewed in an editor and it is trivial to hover over var to see the tooltip containing the actual type of the variable.

    Even when viewing code on dead trees or in simple text editors, sufficient type information can usually be obtained from surrounding code. Parameters have explicit types in C# and most code depends on common libraries for which the reader has some prior knowledge of the types.

    For these reasons explicitly stating the type of a local in code is usually just noise as far as I'm concerned.

    Explicitly typed locals are still useful in a couple of situations though. When I use explicitly typed variables I think of them chiefly in one of two ways:

    1. As a compile time assertion that the result of an expression is of a particular type. The key consideration here is that I know I want to trigger a compile error when certain refactorings occur. This is typically useful when strongly typed code needs to interface with weakly typed code. Rather than pass an implicitly typed local (or an expression) to a function that takes an Object, I'll declare an explicitly typed local and pass that.

    (Another way of thinking about this is that I've conceptually created a strongly typed function that wraps the weakly typed function and then optimized away all the text that makes up the wrapper function except for the _parameters_ which become local variables in the calling function).

    2. As a way of constraining the dependencies on external code to a minimal set either for correctness of my current code or to preserve options for changing an external dependency without changing my code. Commonly in this situation, the explicit type is an interface.

    (Another way of thinking about this is that I've conceptually created a wrapper function around an external dependency where the _return type_ is a facade then I've optimized away both the wrapper function and the separate facade because the underlying object already implements the facade as a separate interface)

    In both cases, use of explicitly typed locals is related to managing dependencies that are external to the local function, refactoring and code maintenance are key to the decision process, and the use of explicitly typed locals can be viewed as optimizations of techniques that would otherwise require me to create separate functions.

  7. Alex Stockton says:

    Olivier, I would caution against using a cast in that way. If your initialization expression is not actually of the type you're casting to, you could end up with an exception at runtime instead of being notified by the compiler. Better to be explicit with the variable type (or if lining up the text is super important, emulate a C++-style static_cast with a generic function that just returns it's argument). 

  8. Mark says:

    I've encountered a situation where explicitly typing a variable caused problems. This was several years ago when Linq and Linq to Sql where new and not well understood by most develpers. There was some code consuming a LinqToSql data source and the developer explicitly stated a type for one of his intermediate queries. The type he stated was IEnumerable<T>, when what would have been implied was something that implemented IQueryable<T> (and therefor IEnumerable<T> as well). Of course the problem wasn't detected until the project rolled into production and had a massive database sitting behind it. The result being that the entire table of data was shipped to the application and the query handled in application code. Had he only typed "var" instead of trying to be explicit things would have been fine.

    This example clearly falls into the category of changing the semantic meaning of the code, but in a subtle enough way that the developer (and presumably some QA engineer) failed to detect it.

  9. Robert Davis says:

    I know that not all development happens in Visual Studio, but most does. If you REALLY need to know the type of a variable, you can hover your mouse over it and VS will tell you what type it is. AutoComplete also readily shows what methods are available. I get the warm fuzzies knowing that C# is strongly typed and that prevents a whole class of errors but it is rare that needing to know the type of something is ever that important.

  10. sukru says:

    @David: I believe in those cases you should abstract the methods to an interface definition, so that you can explicitly tell the type, also change the concrete implementation if the semantics are preserved.

    But overall I prefer using var to explicitly declaring types. If there is one more thing compiler can do for me, and one less I have to care about, it's a nice feature.

  11. Jerry Pisk says:

    Eclipse has a nice feature that highlights (and lets you refactor) code that uses types more derived than necessary. If all you do is enumerate over the return value of ParseAttributeList() then you should type it to IEnumerable (or its generic version). That way your code explicitly states that you are free to change the actual type to anything you want as long as it implements IEnumerable. Using var does not show that. In my opinion it makes the code more difficult to read because it is not clear about what the return type is expected to be. There's nothing to say that if you are going to change it you must implement IEnumerable, unless of course you scan *all* the code that uses the return value. In your example it's right there, in a real world code it may not be. It may be enumerated in a different method we're passing the return value to.

    That said, anonymous types, and maybe even things such as collection iterators, are a reasonable place to use var. But other than that I believe it leads to code that is easier to write but difficult to read.

  12. Stuart says:

    I've more or less switched over to using "var" for almost everything, but I've found one unexpected situation where it's caused problems – and that's with the "dynamic" type. I've got a little helper library that implements json as "dynamic" so you can do "var json = Json.NewObject(); json.x = "y";" and have json.ToString() return {x: "y"}. The 'var' in this case evaluates to 'dynamic' – so far, so good.

    Then you have a method that takes one of these as a parameter – say, IThingy CreateThingyFromJson(dynamic json).

    Then you write code like this:

    var myThingy = CreateThingyFromJson(json);

    … and 'var' evaluates to 'dynamic' rather than to 'IThingy', even when there's only one CreateThingyFromJson method in scope and it literally takes a 'dynamic' as its parameter. Oops. That was unexpected.

    I sort of want a way to declare that I'm using a 'dynamic' undynamically…

  13. Keith J. Farmer says:

    I've been using var almost exclusively since the betas.

    One thing that has not been mentioned, and which figures strongly into my motivations for using var, is its effect on design of code.  Var, by its nature, can act as a forcing function toward simplicity of the code.  That is:

    If your source cannot be reasonably understood using implicit typing, then you should consider rewriting it.

    Doing so helps keep me honest about maintainability.

    @Stuart:  That feels like a compiler bug to me, not an issue with implicit typing in itself.

  14. John says:

    Unfortunately a simple comment doesn't lend itself well to a proper response. You really need a full blog post to do so.

    That being said… I use var almost everywhere, (even in simple for loops!). About the only place I don't is where Jerry Pisk mentioned already. I know others who use var only in the case of linq. One interesting reason mentioned is refactoring code could potentially cause a situation where one doesn't know what the return type of a method call was when it breaks. My preference is what Eric and sukru mention. It is one more thing the compiler can do for me and when refactoring etc. as long as I don't change the semantics it is all good and should work. This is true progress!

    In my opinion, anyone who is dependent completely in explicit typing is either old school and resistant to change or creating methods with much too much complexity. Your methods should do as little as possible and do it well. I think this is where the real "argument" occurs. If you see allot of Explicit typing in your code then your code is quite possibly in need of refactoring.

  15. Joe says:

    "Contrived" apparently means "any situation which I doesn't support me".  

    I do think that "var" hurts maintaining and later changing of the code.  When I change the return type of a method, I want it to be obvious that I messed up an assignment:

    1:  var foo = someMethod();

    45: foo.methodNotThereOnNewType();

    I want it to fail on line 1, not line 45.  Especially if I didn't write the code the first time around.  I hate wasting time on things like that.  Not contrived at all.

    The useful and non-confusing scenario would be "var foo = new Something();" were it is obvious what the type is.  I don't need to look through some method in some other file to know it is a "Something", and it can't fail in a third location by someone changing a method return type in another module.

  16. Ben says:

    @Alex Stockton, the compiler will error out on a cast that is determined at compile-time to be impossible. Just as you cannot "Car a = new Elephant()", you cannot "var a = (Car)new Elephant()".

  17. Alex Stockton says:

    @Ben. Right, but your examples don't negate the point that a cast can easily change something that you want to be a compile time failure in to a run time failure. C# casts should not be used for documentation purposes nor to assert things that you want to ensure at compile time.

    The following are not equivalent:

    1. var x = (Car)CreateTaxi();

    2. Car x = CreateTaxi();

    3. var x = CreateTaxi();

    Suppose the return type of CreateTaxi was originally Car then CreateTaxi gets updated so that the return type becomes Vehicle. A cast from Vehicle to Car is possible, so 1 will still compile, and will result in a runtime cast that can fail.

    Suppose the object returned from the new version of CreateTaxi is actually of type Boat. In this situation 1 will fail at run time, 2 will fail at compile time, and 3 will not fail at all.

    Obviously you have to decide for yourself what behavior you want now and how you want your code to behave when the code around it changes, but compile time failures are preferable to run time failures, so don't cast unless you have to (and you don't have to if what you're trying to do is either fix or document the compile time type of an expression).

  18. S says:

    My God, it's like the VB6 "Variant" datatype never happened.

    The problem us VB programmers had back in the day was Evil Type Coercion(tm). Even if there is no stated type, the programmer will assume a particular type when reading the code. When the compiler picks a different type than the one you assume, hilarity ensures.

    And by hilarity, I mean "intermittent, untraceable, data corrupting bugs".

  19. Matt says:

    The var keyword is nothing like the Variant datatype.  There is no type coercion.  The compiler correctly determines the static type of the variable.

  20. KristofU says:

    Less dependencies means code that is easier to maintain, and without var you're dependent on a typename.

    I try to eliminate dependencies from my code as much as possible. Yes there is a disadvantage sometimes, but it greatly outweighs the advantage.

    Yes birds can hit wind turbines, but regular power plants produce too much pollution.

    Your choice 🙂

  21. Sean says:

    Having the name of the type isn't really a dependency, there are refactoring tools if the name changes and if the return type of the function could change you should probably be using an interface anyways.

    I would also have to argue against var making code more maintainable, at least on a project the size I am on.  It isn't so much that it makes is "harder" to maintain per say, more just frustrating. Sure you can read tooltips to figure out what they are, but trying to keep them straight is annoying and sort of a momentum killer (at least to me)…plus nothing like getting really focused on debugging a difficult bug and then having to stop and switch your brain into "what is this variable?  All i can tell from the code is it has a property named Value that is an object or numeric data type."

    Actually after I joined, I had to debug some year+ old code by someone no longer on the team riddled with vars nested inside foreach loops of vars, and everything was return values of something else.  That led me to push for (and we eventually did) ban the use of var on our project, a lot of times it doesn't hurt, but it is just abused too much in my experience.

  22. Eggbound says:

    Sean, it sounds more like your code was littered with poorly named variables, ie 'value'. I've worked on very large codebases where var is the norm, and can't remember ever having to wonder what the type of a particular variable is, because variables have descriptive names. Its also aided by the fact that 99.999% of the time I dont *care* what the type is, debugging or not. I mean…why would you?

  23. Chris says:

    Lovely . . . more analysis, discussion, and debate about using the "var" keyword.  My solution is simple:  K.I.S.S.  

    I don't see how the KISS principle applies. Is it simpler to state the type redundantly, or simpler to let the compiler infer the type? It seems to me to be a judgment call which is simpler. — Eric

    It's preferable to state something explicitly that shouldn't be than to not state something explicitly that should be.  So . . . .  . state types explicitly unless a syntactic necessity (such as when using anonymous types) and get back to solving the *real* business problem.

    I suspect that you apply your principle inconsistently. In my mortgage example, would you insert casts indicating that the subexpressions were of type decimal? You say that it is "preferable" to state something explicitly, but the types of all those subexpressions are inferred silently, not stated. When, in your opinion, does your principle apply? For example, do you always state the type when calling a generic method, or do you sometimes let the compiler infer the type? How do you decide? Do you always insert redundant casts on method arguments indicating their types to the reader, or do you let the compiler work those out for you? How do you decide? I think your decision-making process is considerably more complex than simply choosing more explicitness every time. I think you probably have some "metric" for determining when explicitness adds value and when it impedes clarity. What is that metric? — Eric

  24. Chris says:

    Hi Eric,

    With regard to the use of the "var" keyword, I was suggesting that the KISS principle be appied in the following manner:

    1.  There are times when explicit typing is preferable to implicit typing.

    2.  Determining situations in which implicit typing (with var) has proved to be a very contentious issue in the developer community.

    3.  The risks associated with always using explicit typing (when possible) are minimal, whereas the risks associated with always using implicit typing are more significant (my opinion).

    4.  So . . . for the sake of simplicity, always use explicit typing.  Some may call this a cop out, but I would call it being practical.  Given the current rate of technology change and the amount of information developers must absorb, I welcome simplicity whereever possible . . . sometimes at a cost.  I'd prefer to not have to work my way through a checklist everytime I declare a variable unless absolutely necesary.

    You are correct.  I suppose I apply this rule inconsistently.  I was thinking primarily of the use of "var" in scenarios such as  "var customer = new Customer();" (these scenarios seem to have received the most attention in many forums).  Looking at things from a broader perspective, I would certainly not want to declare types explicitly in all scenarios.  : )

    In any case, thanks for taking the time to reply.

    Chris

  25. Chris B says:

    I'll second Alex Stockton's notion of using explicitly typed locals as assertions. I like being able to use var where the type of the expression is easily inferred (by humans and the compiler) from the RHS of the expression, as is the case with

    var theList = new List<int>();

    and I love var when I have do something like

    var map = new Dictionary<int, List<string>>();

    However, if the type of the local depends on the return value of a method, I prefer to explicitly type it so that if the return type of the method changes in an incompatible way, the calling code breaks as well. This prevents the class of errors which David Corbin mentioned earlier. Basically, the farther apart the type information for the LHS is from the RHS for the human reader, the more likely I am to explicitly type the variable.

  26. mthamil says:

    There is also a scenario I've run into that would not have happened if the var keyword was used in foreach loops.  Regardless of naming issues and the wisdom of such a design, I've actually seen this type of code in the real world.  

    Say you have the following:  ITest2 inherits from ITest, but Test2 does not inherit from Test.

    IEnumerable<ITest2> items = new ITest2[] { new Test2(), new Test2(), new Test2() };

    foreach (ITest2 item in items)

    {

    Console.WriteLine(item.GetValue());

    }

    Then you change the enumerable to: IEnumerable<ITest> items = new ITest[] { new Test(), new Test(), new Test() };

    The code will compile, but it will fail at runtime with a cast exception.

  27. Ben says:

    @Alex Stockton, your point is clearer now, but the example is not realistic. Why would I write "var car = (Car)CreateTaxi()" unless CreateTaxi() already returned a type that required the cast? In this case, "var car" is no worse than "Car car", since the compile-time error check (on the cast) is the same.

    I agree that casts "should not be used for documentation purposes", but I think another example is required to illustrate this ideal where var is concerned. (I leave it to you to provide one.)

    FWIW, I use var nearly everywhere. As for K.I.S.S., I find the principle applies: var visually and lexically simplifies my code, which translates into faster, easier reading.

  28. Gabe says:

    Considering the way Haskell programmers complain about how often they have to write types in F# programs, I'd have to say that naming types almost seems like a micro-optimization. Why worry about types except in the few cases where it matters?

  29. Dim=var says:

    Great, now C# has the equivalent of BASIC's Dim.

    Next up is GOTO: continuations!

  30. philip.sturdy@ntlworld.com says:

    @Dim=var

    No it doesn't

    Dim doesn't have any equivelent in C#.  What C# has (with var) is the equivelent of Option Infer (actually, I think C# got var first)

    While talking about VB, most people seem to say that var is good in situations like

    var o = new SomeObject();

    instead of having to repeat the type.  This is something that VB already has by being able to say

    Dim o as new SomeObject

    I think removing the extra typing in both cases is good.  I personally would probably prefer a specific syntax for this circumstance (as in VB) but that comes from my general dislike of var.

    My feelings towards var (and Option Infer) are that they are removing some of the benifit I get from a strongly typed language, hence I prefer to be explicit about types.

  31. Alex Stockton says:

    @Ben, I feel like some context is being lost in this thread. To summarize: Olivier said "consider that it is possible to use a cast as a type annotation" and provided code comparing type annotation as a cast and type annotation as an explicit type on a local. In response, I said "I would caution against using a cast in that way". Then you said "the compiler will error out on a cast that is determined at compile-time to be impossible". My response (summarized) was that your statement, while true, is not relevant to the reasons that it is not advisable to use a cast solely as a way to make a type explicit in code. Based on your latest comment, you apparently agree that it is not advisable to use a cast as a way of making a type explicit in code, you also seem to agree that making the type explicit in code is of limited value and so, like me, you use var most of the time.

    Since we're in agreement, I don't have much to add except that perhaps you interpreted my comment "better to be explicit with the type of the local variable" separately from the context. I can see that it would have been much clearer if I had said "if you think stating the type explicitly in code is important and if you are considering using a cast solely for that purpose, don't do that because it would be better to be explicit with the type of the local variable".

  32. Ben says:

    @Alex, I admit I didn't read Olivier's comment closely. Now that I look again, I see why you took the tack that you did, and I absolutely agree that using var just to make declarations line up is a bad practise. Apologies for the misunderstanding. 🙂

  33. IMil42 says:

    I was surprised by Stuart's comment. It even seemed to me that he must have done something wrong (sorry mate), but the quick test showed that yes, indeed my compiler behaves in the same way:

       interface IThingy

       {

           bool Orly();

       }

       class Thingy : IThingy

       {

           public bool Orly()

           {

               return true;

           }

       }

       class TestClass

       {

           public IThingy CreateThingyFromSomething(dynamic whatever)

           {

               return new Thingy();

           }

       }

       class Program

       {

           static void Main(string[] args)

           {

               dynamic val = 42;

               var myThingy = new TestClass().CreateThingyFromSomething(val);

               myThingy.Orly();

               myThingy.WhyAmIDynamic(); //why indeed? this gives an error at runtime, not at compile time

           }

       }

    Now I would like to apologize to Eric for my laziness – maybe I didn't read the C# specification thoroughly enough. What is the reason of such behaviour? Or is it really just a bug (with a simple workaround, I admit)?

  34. Stuart says:

    I think the behavior of dynamic is completely self-consistent, even if it's a little unexpected. "dynamic" means "all operations with this value will be resolved at runtime". Not "We'll make some attempt sometimes to resolve some operations at compiletime but if we can't do that it'll be done at runtime".

    So I think the current behavior is technically correct, but it'd be nice if there were some way to override it.

  35. DRBlaise says:

    @Stuart-"I sort of want a way to declare that I'm using a 'dynamic' undynamically"

    C# already has a way to treat a 'dynamic' undynamically or to "override" the behavior: cast to object.

    var myThingy = new TestClass().CreateThingyFromSomething((object)val);

    I know it feels unnatural to cast a dynamic variable to object on a function that takes a dynamic parameter so that the method returns its actual type, but I don't think I would want C# to introduce another syntax just to handle this situation.

  36. Jerry Pisk says:

    @Eggbound: "I've worked on very large codebases where var is the norm, and can't remember ever having to wonder what the type of a particular variable is, because variables have descriptive names."

    That is what Hungarian notation is, you move your type information into your variable names and we all know where that went. Unless somehow you are able to deduct that "customers", which is a pretty descriptive name, has to actually be ICollection, or even IList instead of just IEnumerable. Or that eventCount must be long and not just an int because it's counting events that have the potential to overflow int sized counter.

  37. IMil42 says:

    @Stuart – oh, yes, now I see where I was wrong.

    Dynamic allows double dispatch, so if the reference to Thingy would be obtained using anything more complex than a "new" operator, the resulting type would be unknown.

    Unknown means either object or dynamic, and since we are already dealing with dynamics, the latter option is more reasonable.

    So everything is correct except my intuition 🙂

  38. Szindbad says:

    iMil42: What? The static type of myThingy can be infered from CreateThingyFromSomething method. Your intuition is correct. The implicit type of myThingy sholud be IThingy.

  39. Alan McF says:

    A real life case where 'var' went wrong for me:

    void Foo()

    {

     var data = GetState();

     ThreadPool.QueueUserWorkItem(_Runner, state)

    }

    void _Runner(object state)

    {

      var data = (DataA)state;

      … use data …

    }

    Then GetState changed to returning a type DataB.  All fine at compile-time…  Big bang when this (infrequently called) code path was used — yes I caught in developer-test but might not have…

    So my one rule: Do not use var when passing the variable to a 'untyped' (i.e. type object) parameter…

  40. Mark says:

    Any chance for "var everywhere" in C# 5.0?  Fields would be nice…

    class Stuff

    {

    private Dictionary<string, List<decimal>> _prices = new Dictionary<string, List<decimal>>();

    }

    with less code noise, less distracting, to simply:

    class Stuff

    {

    private var _prices = new Dictionary<string, List<decimal>>();

    }

    Thanks.

  41. Alan McF says:

    @Mark:

    Eric has previous covered that, see: blogs.msdn.com/…/why-no-var-on-fields.aspx

  42. Mark says:

    @Alan:

    Appreciate these issues, we all tell others that "it's not so easy and here's why"…but…

    "Doing so would actually require a deep re-architecture of the compiler."

    There was a recent video on Channel 9 with Eric and Erik and "compiler as a service"…low level rewrite…any hope?

    -M

  43. SolutionYogi says:

    Alan,

    How is 'var' the cause for the bug in your case? Let's say you wrote it as

    DataB data = GetState();

    ThreadPool.QueueUserWorkItem(_Runner, state)

    Your _Runner method will still fail as there is no type check performed by the compiler. Using or not using 'var' in this scenario won't make any difference.

    Yogi

  44. Ben says:

    I don't know if there's any relation, but var makes me think of duck typing.

    I'm more on the pro-var side, personally – I don't care what type GetThingy() returns as long as the Thing it returns will Frob() as requested.

  45. GreenMoose says:

    Another disadvantage with using implicit typing: "Find usages"/"Find references" on a type will not find occurrences where implicit typing is used.

  46. Olivier says:

    @Alex: I do agree that using a C# cast as a type annotation is dangerous. I was considering syntax and readability (and comparing with other languages), not semantics.

    @GreenMoose: Find References works fine with implicit typing.

  47. GreenMoose says:

    @Olivier: It does?

       class Foo { }

       class Bar {

           Foo GetFoo() { return null; }

           void GetFooWithImplicitUsage() { var Foo = GetFoo(); }

           void GetFooWithExplicitUsage() { Foo Foo = GetFoo(); }

       }

    "Find all references" on type Foo will not find usage in GetFooWithImplicitUsage() with my vstudio2010…

  48. Olivier says:

    @GreenMoose: Our definition of "working fine" differ. GetFooWithImplicitUsage is not listed, but neither is GetFooAndPrintIt:

    void GetFooAndPrintIt() { Console.WriteLine(GetFoo()); }

    Unless your coding style also forbid writing GetFooAndPrintIt, "Find all references" does not guarantee to list all usage of *instances* of type Foo.

  49. steveg says:

    Good article, nice emphasis on the real world. Most code is written for really dull purposes. Code lives long long after it goes live. The simpler code is to understand at a glance the better. I scream while reading code, "Don't make me think!" if it's being complex for no purpose. I wonder how much code like that I wrote when I as younger… eeek.

  50. Jeff says:

    I, for one, think it's insane not to explicitly type variables. It's lazy coding. When some of you say, "if you want it to break if a change is made, then you've got bigger problems, blah, blah, blah". You are naive if you think your code is that 100% perfect, especially organizations with large teams working on a codebase. You NEED code to break if something is changed incorrectly. And the faster it breaks the better, so it can be fixed.

    Not being explicit is like going into a dark room every night to "be" with your wife, whoever your wife happens to be that night. No thanks. I'll choose who my wife is. And if it's not my wife, I'd like the option of knowing ahead of time.

    Leaving your racy analogy aside, I have a serious and not rhetorical question. If it is "insane" to not type your variables explicitly then why is it "sane" to type your subexpressions implicitly?  You're saying that this is insane:

    var customer = new Customer();

    OK, I'll accept that you think that is insane. Is this sane or insane?

    string fullName = (string)customer.FirstName + (string)" " + (string)customer.LastName;

    Most people would say that is insane. Most people would write

    string fullName = customer.FirstName + " " + customer.LastName;

    Why is it unacceptable to implicitly type your variables, but perfectly acceptable to implicitly type the *anonymous* variables the the compiler generates on your behalf when computing values of subexpressions?

    Like I said, this is a serious question. I really do not understand why so many people think that the type of a variable being extant is crucially important if the variable has a name, and absolutely positively must be inferred implicitly when the variable does not have a name. They're all just variables; some of them have names in the source code, some of them have types in the source code. Why should those with names have to have types, and those without names must never have types?

    — Eric

  51. Andrew Bingham says:

    Out of ignorance 🙂

    1.  Does  the scope of an implicitly typed variable affect comprehensibilty etc – I am thinking of a "large" application perhaps with a lot of components?

    2.  Does anyone know of any research on the use of implicitly typed variables – defect metrics, testability, MTBF etc?

  52. G2one network says:

    thank for sharing your great think…..

  53. pet says:

    Eric:

    > Is this sane or insane?

    > string fullName = (string)customer.FirstName + (string)" " + (string)customer.LastName;

    You're missing the point. Jeff wants code that breaks when the type of subexpressions change. Casts prevents that.

    Code like this:

    var IsValid = IsStringValid("somestring");

    should *not* compile if IsStringValid() doesn't return a boolean value.

  54. Alex Stockton says:

    @pet – I understand your point and Eric probably does too, but let's address your concern about the casts.

    First define a cast function that looks something like this:

    T static_cast<T>(T value)

    {

       return value;

    }

    I hope you'll agree that this function allows type annotation, type checking, and limited type casting without allowing runtime failures of the kind that you're concerned about.

    Now let's rephrase Eric's question using this function. Is the following sane or insane:

    string fullName = static_cast<string>(customer.FirstName) + static_cast<string>("") + static_cast<string>(customer.LastName);

    If it's insane is the insanity related to the fact that C# doesn't have a static_cast-equivalent built in to the language or is it related to the fact that annotating subexpressions with types is insane all by itself?

Skip to main content