Why would var be a bad thing?
Asked Answered
S

18

64

I've been chatting with my colleagues the other day and heard that their coding standard explicitly forbids them to use the var keyword in C#. They had no idea why it was so and I've always found implicit declaration to be incredibly useful when coding. I've never had any problems finding out what type the variable was (you only hover over the variable in VS and you'll get the type that way).

Does anyone know why it would be a bad idea to use the var keyword in C#?

Snatch answered 13/2, 2009 at 11:26 Comment(10)
I wonder if this decision was a majority/consensual decision of the development team or if it was single handedly declared by some manager.Garret
@DrJokepu: I didn't ask since we switched subject to LINQ goodies. But I wouldn't be surprised if it was declared by a manager of sorts.Snatch
You should feel lucky for not having to work with code standard like here: thedailywtf.com/Articles/Astigmatism.aspxAlbertinealbertite
You do not (usually) get the type when hovering over the variable if someone has (quite helpfully) decorated the type with the DebuggerDisplay attribute.Poler
var is actively ENCOURAGED in the C# coding standards, so it would be fruitless to go against that guideline. var is there for good reason. And it's perfectly obvious what the type is even without hovering over it. var x = new Customer(); It's a Customer object. Simple :)Attributive
@Attributive "so it would be fruitless to go against that guideline" No it wouldn't. When is favoring ambiguity over clarity in programming ever a good thing? That's a pretty weak example which doesn't cover all usage. What about var foo = bar.Coords;? What is Coords? An array of floats? Ints? A different object entirely? If you have to rely on your IDE to provide that clarity, then there is something seriously wrong with your coding standards. And god help any new programmers you bring into the fold.Actinomorphic
No reliance on IDE. It is perfectly clear from source code.Attributive
var was introduced to support anonymous types which (I may be wrong) I believe was largely to support LINQ. So it should be limited to these usages IMO for all the readability reasons stated here. C# is a strongly typed language and should be written to look like it when possible ... again IMO.Prejudge
@Attributive "var is actively ENCOURAGED in the C# coding standards[...]" Maybe this sentence was true when it was written (2016), but it is not anymore. Here is an excerpt of this same coding standard as of 2023: "Don't use var when the type is not apparent from the right side of the assignment. Don't assume the type is clear from a method name. A variable type is considered clear if it's a new operator or an explicit cast."Washerwoman
If the code is written correctly, then the right hand side should (mostly!) reflect, or at least indicate, the type expected, but I agree, if it would cause confusion, then you don't have to use var. I tend to write my code so that it's declarative and readable, so I never have any issue with a liberal use of var. Swings and roundabouts, I guess :)Attributive
P
82

The writers of the .Net Framework Design Guidelines (awesome book) that came out in November 2008 recommend considering using var when the Type is obvious and unambiguous.

On the other hand, if using var would result in an ambiguity when reading the code, as Anton Gogolev pointed out, then it's better not to use it.

in the book (Annex A), they actually give this example:

var names = new List<string>(); // good usage of var

string source = GetSource();
var tokens = source.Split(' '); // ok; most developers know String.Split

var id = GetId(); // Probably not good; it's not clear what the type of id is

It's possible that, to ensure that readability is not subjected to the whims of lowly developers, your organisation has decided that you were not worthy of var and banned it.
It's a shame though, it's like having a nice tool at your disposal but keeping it in a locked glass cabinet.

In most cases, using var for simple types actually helps readability and we must not forget that there is also no performance penalty for using var.

Propulsion answered 13/2, 2009 at 11:41 Comment(12)
The big think I think everyone misses in this war is "hover over the variable" I can't see what GetId() returns here, but how often do you read complicated code that isn't in your IDE? Tooling is an important part of the language.Chaparro
@alchemical: well what does GetId() return without looking up the interface or hoover over the item?Arbitration
@PoweRoy: I think that was his point - it's always obvious when explicity typed.. long id = GetId();Lusk
Based on your examples, using var with LINQ statements is a bad idea because "it's not clear what the type of id is".Mouth
@ColeJohnson LINQ did not exist at the time the book was released. Nowadays, we use var for complex types (LINQ, lambda) but the rule of thumb remains true since these types are defined where they are declared and there usually no real ambiguity. If there is, then the declaration should probably be explicit.Propulsion
@DefenestrationDay: unless you're writing it for the first time. You can always type out var id = GetId();. If I assume GetId returns int, and type it int id = GetId(); now I have a compilation error if GetId returns a GUID. I still have to look it up.Cullan
There are plenty of times where you don't really need to care what type "id" is. It's something you get from one method call and often pass on to another call, hardly interacting with it at all. It's type is as important to my code as the MacGuffin is in a random Hitchcock film.Swenson
Although this make sense and makes types more obvious to the person reading the code... now you have inconsistent declarations. Some implicit and some explicit, just so you can use vars when its "obviously" easier. Now we must look on either side of the equation depending on the obviousness of the code. If you use explicit declarations to simplify readability, simplify it further by keeping it consistent. Also, whoever thinks its acceptable for people to read by hovering over implicit words with the mouse needs to think again, that will just slow us down and decreases readability.Thermosphere
The only time I use var is for anonymous types and while I'm declaring the variable and i'm unsure what will come back. As soon as I know what type is returned, I replace var with the explicit type.Thermosphere
I "know" String.Split(), but I couldn't immediately remember offhand whether it returned an array of strings or a List of strings.Casiano
var on ambiguous declarations is also a great pain in pull request reviews in web UIs like bitbucket or github. You can't hover the declaration to get the type. Personally I have a very strict policy about it: use var only when using new on the other side of the operation (this includes anonymous types) or when using explicit casting (although I tend to not use var here as well).Egin
@alchemical In the vast majority of cases, the type something's returning doesn't need to be known at a glance. So why would you want to have to hover over variables to see their type? Because it makes the code much easier to read (through not having redundant information cluttering your code) in the vast majority of cases. That's why.Mosora
C
35
var q = GetQValue();

is indeed a bad thing. However,

var persistenceManager = ServiceLocator.Resolve<IPersistenceManager>();

is perfectly fine to me.

The bottomline is: use descriptive identifier names and you'll get along just fine.

As a sidenote: I wonder how do they deal with anonymous types when not allowed to use var keyword. Or they don't use them altogether?

Consubstantial answered 13/2, 2009 at 11:29 Comment(2)
I find that often after refactoring the well named variable indicates the old type and can actually be misleading. If the type is explicit then this kind of problem is easily spotted.Poler
var q = GetQValue(); is not a bad thing. It is, in fact, the C# coding standard recommendation to do so. The type of q would be inferred instantly from the return type of that method. Simple :)Attributive
I
23

In most cases when used sensibly (i.e. a simple type initializer where the type and value are the same), then it is fine.

There are some times when it is unclear that you've broken things by changing it - mainly, when the initialized type and the (original) variable type are not the same, because:

  • the variable was originally the base-class
  • the variable was originally an interface
  • the variable was originally another type with an implicit conversion operator

In these cases, you can get into trouble with any type resolution - for example:

  • methods that have different overloads for the two competing types
  • extension methods that are defined differently for the two competing types
  • members that have been re-declared (hidden) on one of the types
  • generic type inference will work differently
  • operator resolution will work differently

In such cases, you change the meaning of the code, and execute something different. This is then a bad thing.

Examples:

Implicit conversion:

static void Main() {
    long x = 17;
    Foo(x);
    var y = 17;
    Foo(y); // boom
}
static void Foo(long value)
{ Console.WriteLine(value); }
static void Foo(int value) {
throw new NotImplementedException(); }

Method hiding:

static void Main() {
    Foo x = new Bar();
    x.Go();
    var y = new Bar();
    y.Go(); // boom
}
class Foo {
    public void Go() { Console.WriteLine("Hi"); }
}
class Bar : Foo {
    public new void Go() { throw new NotImplementedException(); }
}

etc

Inshore answered 13/2, 2009 at 11:46 Comment(1)
Another example: Changing "Car myCar = BuickFactory.MakeCar;" to "var myCar = BuickFactory.MakeCar;" may not change the code if BuickFactory.MakeCar returns Car, but if a later version of BuickFactory shadows MakeCar to return a Buick, the type of the myCar variable would get changed. If running code tries to assign some other type of Car into myCar, it will fail.Rosary
B
18

Surely this is a mistake. It's because some folk don't realise that it is actually strongly typed, and not at all like a var in VB.

Not all corporate coding standards make sense, I once worked for a company who wanted to prefix all class names with the company name. There was a massive rework when the company changed it's name.

Battled answered 13/2, 2009 at 11:28 Comment(4)
You mean a Variant, not var :)Disseise
You should be ashamed to admit that you remember! ;-)Battled
Ouch! @ Prefixing classnames with the company name.Snatch
How come nobody mentioned NeXTSTEP :)Evars
L
11

First, as a general rule, coding standards should be discussed and agreed by the team, and the reasoning behind them should be written down, so that anyone can know why they are there. They shouldn't be the Holy Truth from One Master.

Second, this rule is probably justified because code is more times read than written. var speeds up the writing, but may slow down the reading a bit. It's obviously not a code behaviour rule like "Always initialize variables" because the two alternatives (writing var and writing the type) have exactly the same behaviour. So it's not a critical rule. I wouldn't forbid var, I would just use "Prefer..."

Ludwick answered 13/2, 2009 at 11:55 Comment(0)
D
11

You may consider Microsoft's opinion to be relevant, since C# is their language:

"However, the use of var does have at least the potential to make your code more difficult to understand for other developers. For that reason, the C# documentation generally uses var only when it is required."

See MSDN - Implicitly Typed Local Variables (C# Programming Guide), last paragraph.


You should also be aware that var removes the compile-time datatype test on the initial assignment.

var x = "mistake";     // error not found by compiler
int x = "mistake";     // error found

Since most variables are only assigned once, consistent use of var removes almost all datatype tests on variable assignments.

This makes your code vulnerable to accidental changes e.g. those made by merge tools or tired developers.

Deirdredeism answered 9/9, 2014 at 8:59 Comment(0)
R
9

I wrote a blog article on this topic a few months ago. For me, I use it every where possible and specifically design my APIs around type inference. The basic reasons I use type inference are

  1. It does not reduce type safety
  2. It will actually increase type safety in your code by alerting you to implicit casts. The best example in the foreach statement
  3. Maintains DRY principles in C#. This is specifically for the declaration case, why bother saying the name twice?
  4. In some cases it's flat out required. Example anonymous types
  5. Less typing with no loss of functionality.

http://blogs.msdn.com/jaredpar/archive/2008/09/09/when-to-use-type-inference.aspx

Roadbed answered 13/2, 2009 at 13:48 Comment(0)
E
6

var is the latest "how to lay out your braces"/hungarian notation/Camel casing debate. There is no right answer, but there are people who sit at the extremes.

Your friend is just unfortunate they work below one of the extremists.

Enoch answered 13/2, 2009 at 11:31 Comment(0)
H
5

Forbidding it entirely means forbidding the use of anonymous types (which become incredibly useful as you use LINQ more).

This is stupidity plain and simple unless someone can formalise a good reason to never use anonymous types.

Harod answered 13/2, 2009 at 11:34 Comment(0)
C
5

Understanding 'var' in Plain English

I'm going to show you that using AND not using 'var' is about communicating clearly.

I'm going to show examples of cases where using 'var' makes the code easier to read, and other examples when using var makes things hard to understand.

More than that you'll see that how clear 'var' is depends a lot on what you name everything else in your code.

Take this example:

Jake said hello to Bill. He didn't like him so he turned and went the other way.

Who went the other way? Jake or Bill? In this case "Jake" and "Bill" are like the type name. And "He" and "him" are like the var keyword. In this case it might help to be more specific. The following for example is much clearer.

Jake said hello to Bill. Jake didn't like Bill so he turned and went the other way.

In this case being more specific made the sentence clearer. But that's not always going to be case. In some cases being specific makes it harder to read.

Bill likes books, so Bill went to the library and Bill took out a book that Bill has always liked.

In this case it would be easier to read the sentence if we used "he" and in some cases left out his name all together, this is the equivalent of using the var keyword.

Bill likes books, so he went to the library and took out a book that he has always liked.

Those analogies cover the gist, but they don't tell the whole story. See in those examples there was only one way to refer to the person. Either with their name, for example Bill, or by a more general way, like "he" and "him". But we're only working with one word.

In the case of the code you have two "words", the type and the variable name.

Person p = GetPerson();

The question now becomes is there enough information there for you to easily determine what p is? Would you still know what people is in this scenario:

var p = GetPerson();

How about this one:

var p = Get();

How about this one:

var person = Get();

Or this one:

var t = GetPerson();

Or this one:

var u = Person.Get();

Whether the keyword var works in a given scenario depends a lot on the context of the code, like what the names of the variables, classes, and methods are, as well as the complexity of the code.

Personally I like to use the var keyword it's more comprehensive to me. But I also tend to name my variables after the type so I'm not really losing any information.

That said sometimes I make exceptions, such is the nature of anything complex, and software is nothing if not complicated.

Cairo answered 17/6, 2016 at 14:20 Comment(2)
Names, like comments, can get outdated. Types cannot get outdated, they're checked by the compiler.Waldner
@Waldner if by outdated you mean that the code can change so that the comment and names no longer accurately describe what the code is doing, that's true. But that applies to class names as well, you can change a class name so that the name doesn't make sense anymore, just like you can change a variable name. And you can change the code in a class/type to the point were the class name no longer accurately describes what it does. I believe that's a different issue entirely. In that scenario the right thing to do is rename things, regardless of the use of the word var.Cairo
K
4

It can hurt readability if it is misused. However completely forbidding it is a bit strange as your colleagues will have a tough time using anonymous types without it.

Kendall answered 13/2, 2009 at 11:29 Comment(1)
Ask yourself why they are using anonymous types. Names provide information to programmers - they improve understanding.Deirdredeism
W
3

This is really a readability issue with your code.

My personal preference is to only ever use "var" for anonymous types (indeed, if you wish to use anonymous types at all, you'll need to use var), and these mostly come from LINQ queries. In these cases, you have no choice but to use var if your query is projecting into a new (implicit & anonymous) type.

However, C# 3.0 will happily let you use var anywhere you like, outside of LINQ and anonymous types, for example:

var myint = 0;
var mystring = "";

is perfectly valid, and myint and mystring will be strongly-typed by the inferred values used to initialize them. (thus, myint is a System.Int32 and mystring is a System.String). Of course, it's fairly obvious when looking at the values used to initialize the variables what types they will be implicitly typed to, however, I think it's even better for code readability if the above were written as:

int myint = 0;
string mystring = "";

since you can see immediately at a glance exactly which type those variables are.

Consider this somewhat confusing scenario:

var aaa = 0;
double bbb = 0;

Perfectly valid code (if a little unconventional) but in the above, I know that bbb is a double, despite the initializing value appearing to be an int, but aaa will definitely not be a double, but rather an int.

Wine answered 13/2, 2009 at 12:4 Comment(2)
To be honest, I find the example of object initialization equally readable both ways. For me declaration of the type when it's already apparent in plain sight is redundant visual noise.Snatch
Since there's no performance penalty to using var, it's quite a subjective thing. It can get more confusing if you initialize a variable with the return value of another function, though. (i.e var a = MyFunc();) since you now need to know what MyFunc returns in order to know what a is.Wine
A
3

From Department of Declaration Redundancy Department (from Jeff's Coding Horror):

"I use implicit variable typing whenever and wherever it makes my code more concise. Anything that removes redundancy from our code should be aggressively pursued -- up to and including switching languages."

I myself think it is worth taking about, but creating a comprehensive guideline on when to use or not would be overkill.

Androgynous answered 13/2, 2009 at 13:1 Comment(0)
R
3

as of c# 9.0 we don't really need var.

we can simply

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

explicit type and short init.

Rm answered 9/3, 2022 at 6:50 Comment(0)
B
2

Implicit typing is great, and people who flat-out prohibit it damage productivity and invite brittle code.

It's almost like type-safe, compiler-checked duck typing, which is incredibly useful when refactoring. For example, if I have a method which returns a List, and I refactor it to return IEnumerable, then any callers to that method which have used the var keyword and only use IEnumerable methods will be fine. If I've explicitly specified, e.g., List, then I've got to go and change that to IEnumerable everywhere.

Obviously, if any of the implicit-typing callers require List methods, then I'll get compile errors when I build, but if that's the case I probably shouldn't have been changing the return type anyway.

Bullfrog answered 13/2, 2009 at 12:57 Comment(0)
T
2

Eric Lippert sums it up well:

  • 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.

My own opinion: I find it harder to read and a bit pointless with types such as int, string, bool or even a User. It's about readability after all (except where using it with LINQ), so when vars are splattered about it can be harder to read and defeating the purpose of the keyword that the language designers intended it for.

Tantara answered 22/1, 2013 at 21:48 Comment(0)
B
1

I have had cases (when I foreach through a Table.Rows collection) when using var resulted in the type being of some base class rather than the actual DataRow type. That is the only time I have had trouble with var.

Blithe answered 13/2, 2009 at 12:56 Comment(1)
That's because a DataTable's Rows collection is IEnumerable rather than IEnumerable<DataRow>. When you specify the type in the foreach loop, the C# compiler silently puts a cast in there for you. This isn't an issue with var, you were just a victim of an old API that was never updated for Generics. Try doing a foreach/var loop over table.Rows.Cast<DataRow>() sometime and you'll see the difference.Squamation
D
-7

Here are the results of a test I ran on efficiency of var versus explicit typing:

  private void btnVar_Click(object sender, EventArgs e)
    {
        Stopwatch obj = new Stopwatch();
        obj.Start();
        var test = "Test";
        test.GetType();
        obj.Stop();
        lblResults.Text = obj.Elapsed.ToString();
    }

    private void btnString_Click(object sender, EventArgs e)
    {
        Stopwatch obj = new Stopwatch();
        obj.Start();
        string test = "Test";
        obj.Stop();
        lblResults.Text = obj.Elapsed.ToString();

    }

First Label result is: 00:00:00 000034

Second Label result is: 00:00:00 00008

Delacruz answered 1/8, 2012 at 22:58 Comment(3)
You might want to add test.GetType(); to the second function. Secondly, click in both forward and reverse order to account for caching effects. Thirdly, perform the test multiple times and average. Without that, you will have a useless result.Rajah
Why are you doing test.GetType(); on the first but not the second function? This difference makes the results incomparable.Snatch
If you look up the MSIL, var is actually changed to STRING.. So the two functions should be the same.Thyroxine

© 2022 - 2024 — McMap. All rights reserved.