I <3 Steve McConnell*
Coding Horror
programming and human factors
by Jeff Atwood

June 19, 2008

Department of Declaration Redundancy Department

I sometimes (often, actually) regress a few years mentally and forget to take advantage of new features afforded by the tools I'm using. In this case, we're using the latest and greatest version of C#, which offers implicitly typed local variables. While working on Stack Overflow, I was absolutely thrilled to be able to refactor this code:

StringBuilder sb = new StringBuilder(256);
UTF8Encoding e = new UTF8Encoding();
MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();

Into this:

var sb = new StringBuilder(256);
var e = new UTF8Encoding();
var md5 = new MD5CryptoServiceProvider();

It's not dynamic typing, per se; C# is still very much a statically typed language. It's more of a compiler trick, a baby step toward a world of Static Typing Where Possible, and Dynamic Typing When Needed.

This may be a cheap parlor compiler trick, but it's a welcome one. While writing C# code, I sometimes felt like I had entered the Department of Redundancy Department.

department of redundancy department.

Sure, there are times when failing to explicitly declare the type of an object can hurt the readability and maintainability of your code. But having the option to implicitly declare type can be a huge quality of life improvement for everyday coding, too.

There's always a tradeoff between verbosity and conciseness, but I have an awfully hard time defending the unnecessarily verbose way objects were typically declared in C# and Java.

BufferedReader br = new BufferedReader (new FileReader(name));

Who came up with this stuff?

Is there really any doubt what type of the variable br is? Does it help anyone, ever, to require another BufferedReader on the front of that line? This has bothered me for years, but it was an itch I just couldn't scratch. Until now.

If that makes sense to you, why not infer more fundamental data types, too?

var url = "http://tinyurl.com/5pfvvy";
var maxentries = 5;
var pi = 3.14159;
var n = new int[] {1, 2, 3};

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.

You might even say implicit variable typing is a gateway drug to more dynamically typed languages. And that's a good thing.

[advertisement] Peer Code Review. No meetings. No busy-work. Customizable workflows and reports. Try Jolt Award-winning Code Collaborator.

Posted by Jeff Atwood    View blog reactions

 

« Coding For Violent Psychopaths The Ultimate Code Kata »

 

Comments

I also think that is a great new feature in C#. Before I always felt that the VB.Net syntax

Dim reader as new FileReader("blabla")

is far superior. Not that I would ever use VB.Net for anything serious though :)

Daniel Lehmann on June 20, 2008 03:40 AM

What do you mean by redundancy?

Niyaz PK on June 20, 2008 03:43 AM

What do you mean by redundancy?

Niyaz PK on June 20, 2008 03:44 AM

The new C++ standard (C++0x) seems to have moved towards this with "auto", so instead of this:

vector<string>::const_iterator it = names.begin();

you will be able do this:

auto it = names.begin();

Assuming someone actually implements it ;-) Although I do wonder how this plays with inheritance. e.g. Would var be the most generic type available or always what you tell it to be (I guess the latter, since it makes most sense).

Ah, I hope ">" and "<" aren't eaten by the post demon. Otherwise the vector was of strings there.

Richard on June 20, 2008 03:55 AM

I agree that in the examples above, but when it comes to variables being assigned through a call to a function (something like var x = GetSomeCrazyStuff(x,y)) the data type in front of the variable makes it easier to figure out what GetSomeCrazyStuff is supposed to return.

SomeGuy on June 20, 2008 03:58 AM

Amen! Now we just need to get rid of "var" ;-)

Andrew Peters on June 20, 2008 03:58 AM

Gets even worse with generics. Nothing like typing

Map<String, Map<Long, Point>> bla = new Map<String, Map<Long, Point>>();

J. Stoever on June 20, 2008 03:59 AM

Agreed. I use var all the time. It could be even more concise if they dropped the "var"

url = "http://tinyurl.com/5pfvvy";
maxentries = 5;
pi = 3.14159;
n = new int[] {1, 2, 3};

Another favorite is the ?? operator (null coalescing operator)

Console.WriteLine(name ?? "it's null dude");

Mike on June 20, 2008 04:00 AM

Bleh, comment software ate my less than and greater than signs. One more try:

Map<String, Map<Long, Point>> bla = new Map<String, Map<Long, Point>>();

J. Stoever on June 20, 2008 04:00 AM

Someone wrote excellent article exactly about this in 2003 when Bruce Eckel and then Jeff Atwood was blogging about how hot Python is.

read his reaction, it's very very thoughtful
http://www.xoltar.org/old_site/misc/static_typing_eckel.html

lubos on June 20, 2008 04:01 AM

Also,

myEvent += new MyEventHandler(myEventHandler);

can be reduced to:

myEvent += myEventHandler;

Mike on June 20, 2008 04:07 AM

Any particular interest to "Judy York"?

url = "http://tinyurl.com/5pfvvy";

Carl Joseph on June 20, 2008 04:10 AM

“Anything that removes redundancy from our code should be aggressively pursued”

Actually, that's a pretty strong claim that would need justification. Many people argue that redundancy in code is a *good thing* because it helps catching logical errors in the code – provided the compiler checks all the information; else the redundancy is obviously harmful (because the information might differ).

That being said, I agree with you in this case. Redundancy in variable declaration is useless code bloat. I actually prefer the new notation for another reason: because it prefixes declarations with a keyword, analogously to VB's 'Dim' statement. I've always hated C-like languages for their implied declarations which make the code much harder to parse (even for a human reader).

Konrad on June 20, 2008 04:17 AM

"You might even say implicit variable typing is a gateway drug to more dynamically typed languages. And that's a good thing."

You might even say implicit variable typing is a gateway drug to Hindley-Milner type inference in statically typed languages. ;)

Weeble on June 20, 2008 04:26 AM

Yes, lets remove the variable declaration phrase, that way the compiler has no way to lets us know when we've mistyped a variable name. </sarcasm>

Brian on June 20, 2008 04:27 AM

Don't need 'var' either. Of course it's a variable.

izb on June 20, 2008 04:27 AM

"You might even say implicit variable typing is a gateway drug to more dynamically typed languages. And that's a good thing."

Like PHP ? :)

manu on June 20, 2008 04:28 AM

What you forgot: In the line

BufferedReader br = new BufferedReader (new FileReader(name));

the BufferedReader left can be replaced by an *Reader*. This has even sense; sometimes you must both load ASCII/UTF files and binary files
(InputStreamReader). So br could be a general Reader variable.

This is important because IDE's can point out flaws when you erronously try to access BufferedReader methods in br when br is actually a Reader. Tell how do you avoid to declare types if we have an OO system with inheritance and interfaces if you want to find out
declaration errors in compile time.

TSK on June 20, 2008 04:31 AM

The addition of "auto" and "var" are welcome. For most of the code I write, I don't need something more complicated. But the reason it took some time is probably that it wasn't clear what they should do.

Consider the question of redundancy in variable declarations, sometimes they aren't so redundant. Jeff's example ("Who came up with this stuff?"):

BufferedReader br = new BufferedReader (new FileReader(name));

In Jeff's code it's "obvious" that the first BufferedReader is redundant. But what about The following case?

AbstractReader br = new BufferedReader (new FileReader(name));

You see, the language designer has to consider all cases, not just the one you are using. The person who "came up with this stuff" had to think long and hard about such cases. Apparently they thought that they couldn't figure out what "var" should do, so for the first few versions of the language they opted not to rob the programmer of this flexibility, at the cost of being more verbose.

Language design is HARD.

What should the following C++ cases do (similar issues are certain to exist in .NET):
auto x = 4; // is x int? unsigned int?
auto y = -5; // well, y should be int, right?
auto z = '\0'; // hmmm, char? unsigned char?
auto w = 0; // int again I guess? what if I wanted a pointer?

I am sure that if we look at the standard we will find the answer, and it will be logical and "intuitive". However it took a while to came up with a good answer, and while they're doing that, I'd rather have my verbose code working.

M on June 20, 2008 04:34 AM

That's one of the reasons I hate Java.

Tiago on June 20, 2008 04:37 AM

Damn, made a comment about this over on RefactorMyCode before this appeared in my reader.

I'm going to disagree with you and agree with the c#3.0 language designers: http://msdn.microsoft.com/en-us/library/bb383973.aspx

"Overuse of var can make source code less readable for others. It is recommended to use var only when it is necessary, that is, when the variable will be used to store an anonymous type or a collection of anonymous types."

Damian on June 20, 2008 04:41 AM

Don't you need "var" because you are initializing a new variable instead of assigning a value to an existing one? Of course the compiler could check that VB6-style :-D

PalotasB. on June 20, 2008 04:42 AM

@Niyaz PK

LOL, that was quite funny....

Carl on June 20, 2008 04:42 AM

Always hated C# (and it's brethren) just for that reason (Along with the redundant semicolons and ()s)...

VB9 ftw! (LINQ is tastier here too!)

Yuvi on June 20, 2008 04:42 AM

Declaring a type of the variable is IMHO always a good thing as it helps readability. In most cases the type declared is an interface (or should be). So what you are declaring is not the actual implementation you will be using but a constraint on what might be used.

Goran on June 20, 2008 04:43 AM

Comon Jeff, learn some haskell, ml, lisp, then write articles about programming languages and compiler tricks.

Ramūnas Gutkovas on June 20, 2008 04:44 AM

I actually think that the 'var' addition is good. It removes redundancy, especially for object with long names.

The trick is that you cannot really avoid having two information. And that's because of OO. the first is object definition, the second one object declaration.

Basically, all does 'var' when you declare an object is to say to the compiler that the definition class is the same that declaration class.

However, for simple types, I don't agree...

var i = 1;

just feels wrong.

Philippe on June 20, 2008 04:45 AM

I agree with you 'M', I find cases such as the following to be very useful, especially for the maintainer,

AbstractReader br = new BufferedReader (new FileReader(name));

It tells you a little about the class heirarchy.

George on June 20, 2008 04:51 AM

Moreover, the last example could be:

var n = new {1, 2, 3};

Because as with (var maxentries = 5) it can be inferred at compile time that the expression is an array of all integers.

I think that this redundancy comes from C++ and maybe other languages, where an initialization rvalue, as "new someClass()" is treated as any other expression, which in this particular case happens to yield a someClass object.

Petruza on June 20, 2008 04:55 AM

I find it odd that LINQ uses "let" for local bindings within an expression and not "var".

Still, I'm very happy about having it in C#!

Andrew Davey on June 20, 2008 04:55 AM

I totally agree, implied types is a huge improvement in C#3

Is this in response to your feedback on http://refactormycode.com/codes/333-sanitize-html ?

If so they're wrong and you're right - I would avoid using var for simple value types (I feel "int i = 5;" is perhaps clearer than "var i = 5;", even though both compile to the same thing), but for various collections and lists where you already know what you're dealing with they're great.

Keith Henry on June 20, 2008 04:58 AM

I disagree with you on this. In this example:

BufferedReader br = new BufferedReader (new FileReader(name));

The first BufferedReader is needed to differentiate between that and this:

ParentClassOfBufferedReader br = new BufferedReader (new FileReader(name));

In any case, I think using "var" when the type if known is a lazy way to write code. It makes it harder to read 'cos now I've got to think about what type a variable is and what methods/properties it provides.

Finally, if you don't like the verbosity of C#, why not switch to other less verbose languages? Why misuse a C# feature? And it is a misuse because it goes against the opinions of the language designers.

Bart on June 20, 2008 04:59 AM

I'm surprised at how many people independently bring up the argument by appeal to authority. What is written in the MSDN is often one person's opinion. And seriously, the coding guidelines in the MSDN, offered without any justification whatsoever, are often just counterproductive.

Over on refactormycode.com someone asked “What's the benefit of using "var" …?” Well, Jeff has given a good many. And no, less typing is not one of them, per se. Rather, it's avoiding *needless* typing. Remember: The best code is no code at all.

Konrad on June 20, 2008 05:05 AM

"And it is a misuse because it goes against the opinions of the language designers."

Who, as we all know, are infallible.

Shmork on June 20, 2008 05:06 AM

Sidenote: the D programming language has this too, under the name of auto. Also anonymous classes, anonymous function literals, anonymous nested function literals .. it's very nice for removing redundancy :)

--feep, D fanboy

FeepingCreature on June 20, 2008 05:06 AM

> The first BufferedReader is needed to differentiate between that and
> this:
>
> ParentClassOfBufferedReader br = new BufferedReader (new FileReader(name));

Here's a useful observation for you: this is not *needed*, BufferedReader is implicitly convertible to ParentClassOfBufferedReader. In the extremely rare case when it could really be needed, nothing prevents you from not using automatic type inference.

> Why misuse a C# feature? And it is a misuse because it goes against
> the opinions of the language designers.

Which is why they added "var" into the language, right?

Get a life.

xxx on June 20, 2008 05:07 AM

Actually although anonymous types might be useful for what they're used here I've found them quite more useful in other situations like:

var row = new
{ Id = reader["id"].ToString(),
Name = reader["name"].ToString(),
Age = Convert.ToInt32(reader["age"]) }

if (row.Age > 45 && Name.StartsWith("xxx")
return "oldie";
else
return "young";

or something like that which actually makes (for me) the code more readable.

Jorge on June 20, 2008 05:10 AM

It is usually painfull to understand someone else code's.
Code is not only for you and the compiler.

But if you want to compete for the more compact code ...
It was a funny game in the 80's with C, and it is still the case.

(see "The International Obfuscated C Code Contest" :-)

ECC on June 20, 2008 05:12 AM

(quote)
var sb = new StringBuilder(256);
var e = new UTF8Encoding();
var md5 = new MD5CryptoServiceProvider();
(/quote)

I agree that these are nice, but I've been bitten - already - by maintaining someone elses code where they do something like:

var service = ServiceFactory.Create();

Fantastic. Whats the service? (without running the code - I needed to debug something underneath this). Oh, it's an ISomething, implemented by whatever the .Create creates.

sure comments would have helped, and maybe the design was wrong, but I found myself cursing the inventor of var at the time.

BTW resharper's code formatter converts everything to var for you now. Which is kinda nice, in a consistent way if nothing else.

Nic Wise on June 20, 2008 05:16 AM

I agree with TSK on this one. BufferedReader could also be Reader. And I take advantage of this facility in OO all the time. I guess the var lovers don't.

Explicitly declaring the type of a variable is not code bloat or redundant. It is a necesity in many cases. I will never use var. It only makes things less clear and causes the possibility of the compiler choosing the wrong class type on my behalf. Sure, I could use it when there is no ambiguity. But why have to make the choice. And how do I know that although there may be no ambiguity now, that there won't be ambiguity in the future.

I never buy arguments that are centered around reducing typing. The amount of typing saved in this instance is a one time cost and significantly less that the amount of time that could be wasted tracking down errors in the future.

Matt on June 20, 2008 05:20 AM

Indeed, Nic Wise, I absolutely hate when other people use it to store the result of a function call. Code isn't just read in an IDE with Intellisense available. I personally only ever use 'var' in LINQ, and anonymous types in general (which, to be honest, I don't particularly like much outside of LINQ either).

TraumaPony on June 20, 2008 05:26 AM

Taking the example, I would really prefer this:

StringBuilder sb = new(256);
UTF8Encoding e = new();
MD5CryptoServiceProvider md5 = new();

because it is easy to directly see what is the type of the variable

It also permit to have a

Set setOfHelper = new HashSet();


DomreiRoam on June 20, 2008 05:28 AM

What about inherited types?
Base b = new Subclass();
How can you shorten this?

Also, Philippe said:
"However, for simple types, I don't agree...
var i = 1;
just feels wrong."
It should feel wrong. The '1' can be a byte, sbyte, short, ushort, int, uint, long, ulong. It makes a difference what type it is.

With the IDE helping you type with CTRL-space, why shouldn't you type the whole thing.

Side note: my longest variable name in production code was:
TimeOfFlightToObjectInFourcoseconds

P.S. A fourcosecond is equal to 4 picoseconds.

Fred on June 20, 2008 05:29 AM

I'm not a fan of the overuse of var and honestly, I think it was introduced in to the language to let linq and anon types work. Without linq, I don't think we'd have seen this language feature.

I've been round and round in circles on this for the past 8-6 months, and I really feel that it hinders readability if you're ever assigning from method calls, when you're using interfaces, and makes variable declarations look messy and unstructured (this, however, is a matter of taste).

It always feels like in the long run, adding dynamic language features to staticly typed languages reduces the usefulness of compile time checking.

I believe code should be practically self documenting in its readability, and I think that using generic declariations like var or VBs Dim reduces this quality.

David Whitney on June 20, 2008 05:34 AM

You should give Python a shot - you don't have to deal with any of this unnecessary verbosity.

Guido van Rossum on June 20, 2008 05:41 AM

'var' is not redundant, it indicates you're declaring a new variable, and not simply making an assignment to an existing variable.
Scala has a powerful type inferencer, with var and also val (for values that won't change).
I know, nobody asked.

German on June 20, 2008 05:42 AM

In VB, you really have a choice with verbosity.
Dim r as New SQLDataReader()
or
Dim r as IDataReader = New SQLDataReader()

We can repeat ourselves if we want to, but only if necessary.

Jay on June 20, 2008 05:57 AM

Ugh! Call me a crotchety old codger, but I really dislike all these latest language "enhancements" that push type checking off to runtime. This is BAD. Static typed languages keep the coder honest by catching mis-typed assignments or usages at compile time. That is when invalid type errors should be discovered. They should not be discovered by your users. Not declaring the type of your variable before you use it opens your code up to problems down the road.

Grandpa Coder on June 20, 2008 05:58 AM

Var is useful, but don't overdo it. I think it's fine for LINQ and constructors, but properties and method output are a bad idea because maintenance can be tricky. If you change the called method or property to return a different type, you can get unpredictable results. For instance, suppose you change a method to return an int instead of a float? Or vice versa? The call will work, but you can have comparison issues (in the case of going from an int to a float) or data loss (going from a float to an int).

Dave on June 20, 2008 06:00 AM

FeepingCreature wrote:
> Sidenote: the D programming language has this too, under the name of auto.
> --feep, D fanboy

D is the greatest language I've ever used.

FeepingCreature on June 20, 2008 05:06 AM

M wrote:
> Language design is HARD.
> What should the following C++ cases do (similar issues are certain to exist in .NET):
> auto x = 4; // is x int? unsigned int?
> [...]

D is working on fixing this too, by saying x here would have multiple types at the same time, and it doesn't get one specific one until it is required. I'm not sure how it will work without breaking D's strong typing, but Walter Bright (D's designer) seems to think it will work.

Right now, it works so x would be an int; if you want an unsigned int, it would be 4u. But D has a lot of cool stuff coming in the future that may fix that too.

Adam D. Ruppe on June 20, 2008 06:01 AM

(quote)
If that makes sense to you, why not infer more fundamental data types, too?

var url = "http://tinyurl.com/5pfvvy";
var maxentries = 5;
var pi = 3.14159;
(/quote)

I can see where the use of implicitly typed variables for fundamental data types would be beneficial, but the example above shows me that there might also be a tendency to use them as a replacement for constants, which I am a bit leery of.

mark on June 20, 2008 06:10 AM

I have to say I'm not a big fan of this. The idea of typing a variable based on a literal just brings back the horrors of accidental integer division.

Ryan Clare on June 20, 2008 06:12 AM

Amen Grandpa Coder!

JohnM on June 20, 2008 06:14 AM

It does feel a bit bolted on in C#. If a language is designed from the ground up to be dynamically typed it often works much better, especially when taking into account that dynamically typed languages typically have other accepted coding standards, i.e. it should always be as easy for the programmer to infer the type as it is for the compiler.

I also don't agree with the statement that we should remove redundancy at every expense (though I know Jeff probably didn't mean it that extreme). When writing anything that will be read by other people, including code, you are bound to introduce redundancy. Redundancy simply helps us understand. When writing longish e-mails on technical subjects, I often find myself spelling things out and repeating myself multiple times. Beats having to have a conversation about 15 messages long about what exactly you meant instead of the problem at hand.

The same thing goes for code really; having seen how awfully bad even programmers can be at reading comprehension I err on the side of caution and usually write my code a bit more verbose. Of course the more code you write, the harder it becomes to keep it all in your head if you're trying to read and understand it, so there's definitely a trade-off there.

wds on June 20, 2008 06:15 AM

Not to split hairs here, but you're talking about two items combined:

- variable declaration
- variable assignment / object creation

--The difference is between this:
Dim dt As System.Data.DataTable
dt = New System.Data.DataTable()

--And this:
Dim dt As New System.Data.DataTable()

There are lots of reasons to postpone instantiating your objects or assigning data to your variables until after the declaration block. Error handling is one good reason.

Say you want a Try / Catch statement, and in your Catch you want to do something with one of your variables.

--This works:
Dim dt As DataTable
Try
dt = New System.Data.DataTable()
Catch
'Do something with the datatable
End Try

--This doesn't:
Try
Dim dt As New System.Data.DataTable()
Catch
'Do something with the datatable
End Try

If you didn't declare it outside of your try catch block, then you can't access it in the Catch. And you shouldn't put code that instantiates objects outside of a try catch block because if the constructor fails you need to be able to crash responsibly.

Dave on June 20, 2008 06:15 AM

Great observation, I agree 100%. As a developer with over 20 years of software development experience, it is easy to be pressure to get work done and simply use the programming language as you know it and not take advantage of new language or framework features.

As professionals, we need to dedicate time to at least becoming aware of new features of the language(s) we use day-to-day to make our work easier.

In a way this relates to our spoken language, as adults so few people take the time to expand their vocabulary.

Rob Bazinet on June 20, 2008 06:20 AM

Dunno if anyone's mentioned it yet, but there's always the case where you want to instantiate something later:

BufferedReader br;
...
br = new BufferedReader();

I see the redundancy, then, as a way of standardizing the way that variables are declared, whether you're instantiating them immediately or not.

Evan on June 20, 2008 06:30 AM

Much of the time I'm using interfaces. For example in C#:

IDictionary<string, string> myDictionary = new Dictionary<string, string>();

Or in Java:

Map<String, String> myMap = new HashMap<String, String>();

I can see some potential for confusion with this var keyword that makes it not worth it.

Then there is the potential for something like this:

var myVar = getSomething();

Lets say the return type for getSomething changes. If your imports contain the type that it changed to and if the method signatures of the methods you call are the same, you won't have to change this code. But maybe you *want* to be made aware of what code is affected by this change through compiler errors. Lets say the method signatures are the same, but they do something completely different and the code is using it is using it incorrectly now. With var syntax, you have to realize this, and use the find references feature in your IDE to go and correct this, making sure to cover every case. If you didn't use the var syntax, you'd get compile errors everywhere and you'd go and fix it at all those places.

I know that is a crazy edge case that is unlikely, though.

I'm generally all for things that make my code leaner, but I'm not sure of its value. The small savings in number of characters is not enough of a savings to introduce confusion. There would need to be some case where I am copying/pasting a block of code frequently that requires less changes when I use the var keyword. Maybe in test cases it could be of value.

n on June 20, 2008 06:32 AM

Can we get a preview function for comments here? A blog about software should never eat greater than/less than symbols in the comments. I'll try again:

Much of the time I'm using interfaces. For example in C#:

IDictionary<string, string> myDictionary = new Dictionary<string, string>();

Or in Java:

Map<string, string> myMap = new HashMap<string, string>();

I can see some potential for confusion with this var keyword that makes it not worth it.

Then there is the potential for something like this:

var myVar = getSomething();

Lets say the return type for getSomething changes. If your imports contain the type that it changed to and if the method signatures of the methods you call are the same, you won't have to change this code. But maybe you *want* to be made aware of what code is affected by this change through compiler errors. Lets say the method signatures are the same, but they do something completely different and the code is using it is using it incorrectly now. With var syntax, you have to realize this, and use the find references feature in your IDE to go and correct this, making sure to cover every case. If you didn't use the var syntax, you'd get compile errors everywhere and you'd go and fix it at all those places.

I know that is a crazy edge case that is unlikely, though.

I'm generally all for things that make my code leaner, but I'm not sure of its value. The small savings in number of characters is not enough of a savings to introduce confusion. There would need to be some case where I am copying/pasting a block of code frequently that requires less changes when I use the var keyword. Maybe in test cases it could be of value.

n on June 20, 2008 06:35 AM

@Dave: If the constructor call fails, the variable will not be assigned and your "Catch" will also fail. You should always call the constructor BEFORE the "Try".

Daniel Lehmann on June 20, 2008 06:42 AM

And with C++ multiple inheritance, and it would become even more interesting ... (guess who ?).

A good programer is a lazy one, but not too lazy ... and IDE are there for you.

Redundancy helps reading someone else code's.

ECC on June 20, 2008 06:42 AM

Am I the only one that doesn't like this feature? Sure it's all fun and games when it works correctly, but just wait until the compiler casts what should be a float as an int and your entire world collapses around you. Have fun debugging that one.

Kris on June 20, 2008 06:43 AM

> Ugh! Call me a crotchety old codger, but I really dislike all these latest language "enhancements" that push type checking off to runtime. This is BAD. Static typed languages keep the coder honest by catching mis-typed assignments or usages at compile time.

God damn it could you guys stop being such uneducated retarded inbred morons?

var does NOT move type checking to runtime you idiots, type inference is a feature of *statically* typed languages, not dynamically typed ones.

Also, you don't know what you're talking about re dynamic typing, please shut up (here's a hint: the second "high level" programming language *ever*, Lisp, was dynamically typed. There's nothing new to dynamic typing)

masklinn on June 20, 2008 06:44 AM

I'm going to side with the dissenters on this one, Jeff.

If you are going to be the only person ever working with the code, then fine -- but with the pain of having to 'figure out' what someone is doing in the first place, having to check all of the 'vars' all over the place (especially in the term of inherited objects) is not fun.

I'd rather have redundancy and clarity than a lazy typist and obfuscation.

I'm going to side with the MSDN folks on this one -- only use it when you have to use it or when it would really benefit the logic of the code ... not because you're lazy.

N on June 20, 2008 06:44 AM

The problem is not with the variable declaration, it's with the c# instantiation syntax borrowed from C++ and Java.

Really in a language like Java and C#, you ought to be able to in all cases just do this:

StringBuilder builder(x, y, z);

Why they decided to copy C++'s "new" keyword in Java is beyond me.

Maybe it would be a nice shortcut in C++ to allocate and assign a pointer sort of like this:

StringBuilder *builder = new(x, y, z);

...

BTW the reason for the redundancy is that you can do this, don't forget:

StringBuilder *builder = new SuperSpecialStringBuilder(x, y, z);

where SSStringBuilder is a subclass of StringBuilder. The case where your variable and the allocated object happen to be the same class is in a sense a special case -- but it turns out to be the most common one of course.


Reed H on June 20, 2008 06:47 AM

@Grandpa Coder
I'm pretty sure that this still does type checking at compile time. The difference here is that the compiler is supposed to infer the type rather than having it explicitly declared by the programmer. At any rate, C# had a way to push type checking to runtime through the use of the object type.

ricree on June 20, 2008 06:47 AM

(quote)
StringBuilder sb = new(256);
UTF8Encoding e = new();
MD5CryptoServiceProvider md5 = new();
(/quote)

Here here! That was my thought exactly. Much easier to tell what the types of those variables are, and it will force people to think about (and type out) their base classes and interfaces when that's important.

Craptaculus on June 20, 2008 06:47 AM

I personally agree that we should not have to worry so much about the details of converting and setting up variables and more on what we do with them.

As compilers get better at figuring out what type of variable we want, we can be distracted less by variables and focus more on building the solutions.

Jeff Davis on June 20, 2008 06:48 AM

Besides ... usually by typing 2 or three characters I can hit tab and get the declaration I want anyway.

N on June 20, 2008 06:48 AM

I think you have forgotten about abstraction and using base classes to access derived classes. You probabably haven't but the power of polymorphism is the gained poewr that makes those syntactic elements necessary.

If you were going to rail against something, why not the redundancy you see in naming things like this:

ArrayList PersonList = new ArrayList();

where the identifier name is indicating implementation - this could have been:

ArrayList People = new ArrayList();

--/\/\ike

mikester on June 20, 2008 06:48 AM

Just a thought.. why not remove the keyword var also?? So instead of var v = new myobject() v = new myobject()

paramesh on June 20, 2008 06:50 AM

> As compilers get better at figuring out what type of variable we want, we can be distracted less by variables and focus more on building the solutions.

They don't, it's just that the C# and Java compilers suck balls. Compilers in more advanced languages (Haskell, OCaml, Scala) have been able to do not only local type inference but also non-local (e.g. function or method-level) for a long, long time.

masklinn on June 20, 2008 06:50 AM

> Just a thought.. why not remove the keyword var also?? So instead of var v = new myobject() v = new myobject()

Because var is used to disambiguate between creating a new variable in this scope and reusing an existing variable in an upper scope. It's actually one of the things I regret lacks in Python, it makes scoping and scope handling clearer and simpler at an essentially nul cost.

masklinn on June 20, 2008 06:52 AM

@Grandpa Coder

I don't think you understand how var works. It *doesn't* push type checking to run-time. The only difference is that the type is declared by the right side of the assignment operator, not the left:

StringBuilder x1 = new StringBuilder();
var x2 = new StringBuilder();

Both x1 and x2 are StringBuilders and are declared as such. The following lines cause the same compiler error:

x1.Foo();
x2.Foo();

You don't lose any compile time checking, the IL code is actually identical.

Personally, I love type inferencing, though I would say that it's not so much a gateway drug to dynamic languages, but a gateway drug to functional languages (such as F#) which use type inferencing almost exclusively.

Adam on June 20, 2008 07:04 AM

How do you do this with your new cool C# syntax:

List list = new ArrayList();

Something isn't clear about:

var list = new ArrayList();

I guess list variable's type will be ArrayList and now you may accidentally invoke something special to that implementation of List. Isn't it violating the "program to interface" philosophy (or whatever)? I am not in either the strong-typing or weak-typing gang. I'm just curious.

And I am not sure this is a great feature for a strongly typed language like C#. Seems like it's going to make average programmers' life (and the people who review their code) tough. Of course, such type of programmers don't even know what is "programming to interface."

(Don't know C#'s library classes, the above example is in Java.)

-- Srikanth

Srikanth on June 20, 2008 07:06 AM

What is this C# stuff? I thought you "don't enjoy parsing through C#, and any C# code I plan to incorporate into my new projects, I *always* convert to VB.Net". (http://www.codinghorror.com/blog/archives/000128.html)

Anyway, to me, things like this are the primary reason to stick with VB. It's not trendy, but it sure provides a much smoother ride.

MattH on June 20, 2008 07:09 AM

Duh... The simple solution here is just never name any of your classes or types over two letters long. That way "var" becomes the long name!!

h c = new h(); //FTW!!
var p = new mc(); //FTL!

HB on June 20, 2008 07:10 AM

To all those complaining about using base class declaration, I think you're missing the point.

In local scope, you should rarely ever care about a base class at the point of declaration. That's only going to be important when you pass the variable off to another method.

AbstractBaseClass c = new ConcreteClass();

This doesn't buy you anything within a local scope. Within this scope your code will always, by definition, know about the concrete class. If you have some code further down that is going to break by declaring c as ConcreteClass instead of AbstractBaseClass, then you have some refactoring to do.

Adam on June 20, 2008 07:12 AM

Just one more thing Jeff,

between:

var maxentries = 5;

and

int maxentries = 5;

I have trouble seeing which one is more concise... But there is one that is crystal clear ;)

I agree with the idea that 'var' is nice is some cases (declaration = instantiation) but in some other it is no (simple types, values returned for functions...). For arrays I have to say that I'm not sure...

Philippe on June 20, 2008 07:14 AM

To make it simpler, the declaration of the variable should be the popup tooltip when hovering over the variable name.

Jason on June 20, 2008 07:14 AM

I agree with the use of var in cases where you're using "new" and want the same exact type that follows the "new", and it's totally obvious what that type is. The reason is that it makes the code more readable. If there's a lengthy type name (as often happens when using generics), and it's repeated twice in a row, that's more crap I need to parse while reading, and having it repeated doesn't buy me a thing over using var. Then put a bunch of lines like that together in a row.

So, var is worth using in some non-required cases for the sake readability. It just takes a little discretion on the part of the programmer. When I see it abused, I don't curse the language designers, but rather the programmer who abused it - or the person who refuses to fire that programmer.

By the way, those of you who said or agreed with "now we just need to get rid of var!" - that's just stupid. If you don't want a compiler to help you, go use a language that doesn't have one. And using var for cases where you don't specify the type right after the var but easily could have? (like base types) It makes the code less readable and more error-prone, IMO. You'd better specify that type somewhere.

Tom on June 20, 2008 07:15 AM

Hi Jeff,

You should totally check out haXe, it has this sort of inference since very long time.

Also you can compile your code to swf, js and server-side bytecode (that runs on its own VM called Neko).

Check the site out:

http://haxe.org/doc/intro
http://nekovm.org/

Cheers!

Zarate on June 20, 2008 07:18 AM

I'm sorry, but I have never been a huge fan of impicit variables on any type of big or major project. Call me old school (although I'm 24 and haven't used C++ since my 2nd year of college), but I remember doing big project in PERL and running into huge issues because of this. VB.NET syntax has annoyed me since inception.

I agree, there is too much redundancy with Java for example in declarations, but I think some of the new languages have taken it too far and have severely hurt readability in order to save a word here or there.

Honestly, whats the difference between "int i = 0;" and "var i = 0;". Especially when you run into issues of doubles, floats, ints, and longs ... its hell.

My 2 cents

Another Programmer on June 20, 2008 07:23 AM

> I guess list variable's type will be ArrayList and now you may accidentally invoke something special to that implementation of List. Isn't it violating the "program to interface" philosophy (or whatever)? I am not in either the strong-typing or weak-typing gang. I'm just curious.

Given that it's within the body of a function, it doesn't matter one way or the other. The part where coding to interface not impl is important is on the interface of the functions (parameters and return values). Since C# doesn't do nonlocal type inference that's a non-issue: you still specify explicitly the types of your inputs and outputs.

> And I am not sure this is a great feature for a strongly typed language like C#.

1. This feature has nothing to do with strong typing. At all. Whatever "strong typing" means to you (of the dozens of more or less hazy definitions of the term)

2. Type inference is related to *static* typing (where types are resolved at compile-time, rather than run-time type resolution in dynamically typed languages) and languages infinitely more statically typed that C# (as in, languages where "null" doesn't even exist and the "nullability" of a variable is a type in and of itself, or languages where side-effects have to be encoded in the types of your funtions, and languages where you aren't allowed to add a float and an integer without an explicit conversion) have had type inference (of a much more impressive and wide-ranged breadth than that added to C#) for years.

Type inference exists solely and uniquely for statically typed languages by the way, it doesn't really make sense for a dynamically typed language. And it isn't of much use either, beyond basic static analysis and potential optimizations.

masklinn on June 20, 2008 07:31 AM

I welcome the addition of type inference to C#. Anything that can reduce unnecessary redundancy is a good thing. But I wonder if a better, more general, solution would have been to introduce a typedef construct into the language. Actually, I wouldn't mind having both.

Ferruccio on June 20, 2008 07:35 AM

> Call me old school

As I said, that vision is not "old school", it's "uneducated". Implicit typing, be it dynamic or static, has existed ever since languages of a higher level than raw assembly have existed.

> Honestly, whats the difference between "int i = 0;" and "var i = 0;".

There is none, but there is a difference between

Map<Set<String>, List<List<Frob<Bar, Grutz>>> myMap = new HashMap<Set<String>, List<List<Frob<Bar, Grutz>>>();

and

var myMap = new HashMap<Set<String>, List<List<Frob<Bar, Grutz>>>();

That's a pathological case, but it's trivial to encounter cases that come close to that when using generics and trying to leverage the type system for safety.

masklinn on June 20, 2008 07:36 AM

I would also like to say that I agree with DomreiRoam that if you really wanted to cut redundancy, it would be nicer to do it on the new statements (ie List<foo> bar = new() ).

However, the main point of the var keyword is to provide type checking for anonymous variables and other similar cases. To my mind, using this to cut redundancy is somewhat of an abuse of the language.

ricree on June 20, 2008 07:41 AM

var myReader = new Reader() is unambiguous

However

var pi = 3.1415 is ambiguous (is a decimal? float? double?)

Wile_E_Coyote on June 20, 2008 07:50 AM

Another Programmmer,

You're so right. While on the topic, what's the difference between "StarlightFightingWeapon x = new StarlightFightingWeapon" and "x = new StarlightFightingWeapon"?

Oh...24 characters. Hm.

Grace on June 20, 2008 07:51 AM

Anyone typing the class declaration twice in C# is wasting keystrokes. The IDE is your friend.

type: MyClass variableName = new [tab-key].

Done. You now have everything you need to proceed *and* readable type declarations. Personally I dislike var. Just because the compiler is smart and can figure out what type that var is doesn't mean this code is somehow more readable to me, the human involved.

In the case of C# we have a pretty good IDE in VisualStudio and I'd rather that Microsoft spend energy making the IDE more powerful, rather than changing the language to be more dynamic-ish.

There are several good dynamic languages out there. What would be better than debasing C# is to port something like Ruby to VS and CLR.

Michael on June 20, 2008 07:53 AM

Here's a thought, let's infer the datatype from the first character of the variable name. "I" thru "N" are integers and everything else is Floating point... oh wait, I'm showing my age.

Wile_E_Coyote on June 20, 2008 07:53 AM

> It should feel wrong. The '1' can be a byte, sbyte, short, ushort, int, uint, long, ulong. It makes a difference what type it is.

But why can't the 1 simply grow/size to fit? Wouldn't that be preferable to the overspecific data typing and the inevitable integer overflow weirdnesses errors and even *exploits* this results in?

Jeff Atwood on June 20, 2008 07:55 AM

I'm in the 'no sir I don't like' group. It has it's place certainly like with LINQ (for which it was introduced). However I think it's overuse will be something we look back at with disdain in a year or two. I do sincerely hope though that authors (blog and print) will shy away from it when showing code examples.

Ryan C Smith on June 20, 2008 07:55 AM

I find this post very funny considering that the last entry was "Coding for Violent Psychopats".

Also, how hard is to write StringBuilder instead of var on Visual Studio, you just hit CTRL + SPACE and the IDE does it for you.

The problem with this "var" keyword is that while it may sound nice in your example it is going to be overused and it will make code maintenance a nightmare.

Mike G on June 20, 2008 07:57 AM

(TSK seems to be the first to make the point I wanted to make about declaring a field to be a supertype and then assigning it to an instance of a subtype.)

I can't support any type inference or type omission scheme that fails to handle that case. How many times do you want an API to specify that a method returns a type T and not let the fact that your implementation returns type S (where S is a subtype of T) become available to clients of the API?

"BufferedReader reader = new BufferedReader(...)" isn't redundant; it's specifying that two completely different things happen to be BufferedReaders. I do agree, though, that it appears often enough that there should be some syntactic sugar enabling this form to be shorter.

Nathaniel Manista on June 20, 2008 07:57 AM

I believe you have missed the boat on this one Jeff.

Explicit type casting is there for a reason. It lets the compiler know what we want to have in the variable, what should be in the variable, and it can help identify problems when they occur. Your examples are a bit simple too. There are more times when I am assigning a variable from a return function whose return value isn't always clear. Also keep in mind that the constructor doesn't always reflect what is being constructed.

Also, just having the type out in front makes it even easier to read.

Phil on June 20, 2008 07:59 AM

Unfortunately, you and everyone else pretty much got it wrong. While I agree with you that redundancy is not a good thing, the better way to solve this issue would have been to do something like the following:

MyObject m = new();

Or if you are passing parameters:

Person p = new("FirstName", "LastName);

Where in the creation of a new object, the compiler infers the type from the left-hand side, and not the right. This has other advantages over "var", in that it could be used in field declarations as well (there are also some other areas that it could be useful as well, but I won't get into it here).

In the end, it just wasn't intended to reduce redundancy. Don't get me wrong, "var" is VERY important in C# for anonymous types/projections, but the use here is just WAY off (and I've been saying this for a long, long time) as you obfuscate the type that is being used. Having to type it twice is too often, but declaring it zero times is too few.

Nicholas Paldino [.NET/C# MVP] on June 20, 2008 08:00 AM

In C#, using var for value types is a dangerous shortcut that will come back to haunt you at some point.

Consider:

var i = 1;

is i an int, a uint, a long, a short, an int32, int16, int64?

var pi = 3.1.4159;

is pi a decimal, a single, a double, a float?

What are the boundaries of those variables? How would you write a unit test to cover boundary testing? How could you be sure? And, more importantly, will this behavior change with .Net 4.0? (or 3.6 or whatever they call it).

C# is a strongly typed language. And you need to be aware of strongly typed issues such as boundaries and overflows.

Despite being able to make it look like one, it is not a dynamic language. If you want to use a dynamic language, use one. There are a lot of great dynamic languages out there that can consume the .Net framework these days.

A Flurry of Voices on June 20, 2008 08:06 AM

Except some tendencies to overuse, I am not sure what's not to like.
I, for one, welcome our new type inference overlords.

Seriously, it's a nice language feature in both languages, and it can be misused like any other language feature. It will take a while, but people will learn when to use it and when not to use it.

I can certainly see how auto and ptr would help me write code.
Next thing people will complain about the new closures in C++0x I imagine.

M on June 20, 2008 08:06 AM

I'm not a big fan of "var" overuse, either. I've been bitten by the same issues other folks have. I actually take issue with some of the ease of readability, too. For example, a bunch of variables declared in a row, mixing and matching:

IMyInterface a = SomeService.Create();
var b = new XmlDocument();
int c = 7;

I can't just scan down the left side and see the various types; now my eye jumps back and forth from one side to the next, trying to figure out what's going on from a type perspective. And sitting "var" next to "int" makes you look twice, doesn't it? It sounds nitpicky, but if you read a lot of code over the course of a day, it gets really lame really quick.

I really only like "var" in two cases: Anonymous types and really super long type names (like that crazy generic masklinn mentioned above).

Travis Illig on June 20, 2008 08:17 AM

> Also, how hard is to write StringBuilder instead of var on Visual Studio, you just hit CTRL + SPACE and the IDE does it for you.

At least you have your fancy IDEs that can do half the thinking for you. Now if only corporate could get rid of the monkeys all together and replace them with really smart IDEs.

> How many times do you want an API to specify that a method returns a type T and not let the fact that your implementation returns type S (where S is a subtype of T) become available to clients of the API?

Knowing what you're talking about. You need to try it.

C# type inference is *LOCAL*. It does NOT exist at the API level, it only works *within* a function and doesn't bleed out. *You* are still the one specifying explicitly your API.

> Explicit type casting is there for a reason.

Yes, and that reason is lazyness on the part of the compiler writers, and willingness of corporate code monkeys to let them.

> It lets the compiler know what we want to have in the variable, what should be in the variable, and it can help identify problems when they occur.

No.

> There are more times when I am assigning a variable from a return function whose return value isn't always clear.

Hey, guess what? It's optional. If it makes code less clear, just don't use it. Also, you can leverage your shiny little IDE which you like boasting about so much because it prevents you from thinking: it knows the types of your variables, just ask it.

Or even better, reengineer your functions so that what they return is clear.

> is i an int, a uint, a long, a short, an int32, int16, int64?

I know I don't give a fuck in about 95% of the cases.

In the 5% left where I absolutely definitely need to say that something is a short, I can since var is optional.

Then again, I'm used to non-moronic languages where integer types default to unbounded and overflow is an issue gone the way of the dodo.

> How would you write a unit test to cover boundary testing?

Testing is done at the boundary interface of a function, C#'s type inference only works within a function. Non-issue.

> And you need to be aware of strongly typed issues such as boundaries and overflows.
>
> Despite being able to make it look like one, it is not a dynamic language. If you want to use a dynamic language, use one.

Your lack of knowledge about the field of computer science and computing is astounding and, quite frankly, border on frightening.

You don't even remotely know what you're talking about.

masklinn on June 20, 2008 08:23 AM

The truly amazing thing about this post is the number of comments bashing Jeff where the comment's authors are _completed misinformed on var_.

Not that linking to Dare's post helps, of course. As is not uncommon over there, Dare's post twists off on some particular possibility and makes it sound like it is the mainline case. I have yet to see code, in online samples or in production code, where the use of var causes people to go hungarian, and as much as Dare would like to blame it, R# isn't doing anything to encourage going hungarian.

To people freaking out about using var in place of int: It's simple, just int!
To people freaking out about using var for variables assigned from method returns: It's simple, just declare the type!
To people freaking out about var making your numeric types ambiguous: If they are ambiguous with var, you were writing them incorrectly before anyway.
To people freaking out about var taking away compiler checks: Please leave the industry.

It is VERY easy to set a var usage ruleset for use either personally and/or within a team. Maybe your team likes var everywhere. If so, fine. Maybe just on anonymous types and heavy generics, but never when assigned from a method return. Whatever. Just put in places rules for what you are all comfortable with and run with it for a while. There are trade-offs. There are personal preferences. Surprise, surprise, this is just like any other part of a coding standard. Pull up your big boy pants and get back to work.

Jeremy Gray on June 20, 2008 08:24 AM

I think it's funny that you just wrote an article about maintaining code, and now you follow it up by praising a programming convention that was created for lazy people, by lazy people. Your not concerned about the ill-effects of redundancy, your worried about keystrokes. You're like George Bush saying he's worried about terrorists and not oil profits.(FTW!)

I enjoy typing my variables because it reinforces my own understanding of my code and hopefully scares lazy coders into actually thinking.

Shady on June 20, 2008 08:28 AM

C'mon, nobody uses Boo? http://boo.codehaus.org/

The code looks like Python, but the compiler is smart enough to do automatic static typing for you. You can declare variable types if you want to, including a "duck" type which works exactly like dynamic variables do in Python. It's a .NET language, too. Best of all worlds.

steve on June 20, 2008 08:28 AM

Jeff:

Why did you choose to use C# over VB.NET? I thought you were a strong proponent of VB and all it's dynamic glory?

Josh on June 20, 2008 08:29 AM

I have to disagree with you on this. In my opinion, omitting those types makes your code harder to read.

Even on the example you wrote, it still takes *longer* to read the shorter code, because I have to scan to the right for each variable to see what it was. Before, if you had

MD5CryptoServiceProvider md5

well, then I'd know what md5 was, and I could skip on to the next line. Now, if you just have 'var md5', I have to read your entire line to figure out what it is; after all, 'md5' could be the provider, a hash itself, or - if you're evil - something totally unrelated. It could even be some class of your own that also has the initials m, d, and 5! Worse, things like 'var e = new UTF8Encoding()' sound as if you simply picked variable names out of the sky, and started assigning them haphazardly to whatever you needed. var e is....eh, let's put the text encoder there! Is it just me, or does 'UTF8Encoding e = new..', connect the two more closely?

But perhaps this is just how I remember variables (int i, List clientList, DatagramSocket socket, etc), so if I'm the only one who finds this weaker, don't worry too much about it. :]

Phillip Cohen on June 20, 2008 08:32 AM

Using var for reference types is also a bad idea. While you won't have the boundary and type-guessing issues that you have with value types, you wind up with more subtle issues. Issues that make your application a lot more rigid than it appears to be on the surface.

"var" gives coding ease and flexibility. But it leads to development rigidity. Consider:

var mylist = new List<string>();
...
foreach(string s in mylist) {...}

mylist is now a List<string>. It can only be that and will only ever be that. But the only thing I ever do to mylist is to enumerate it. The best practice here would have been to declare it as:

IEnumerable<string> mylist = new List<string>{};

Now the same code will work regardless of the type that mylist becomes.

In this case, using "var" has decreased the flexibility of your application in a subtle way. This method is now more rigid than it needs to be and will take more time in the future to modify.

This is not a fringe condition.

Coding against interfaces is a commonly accepted Best Practice. If you find yourself declaring a lot of reference types as specific types (or using "var") a lot, you need to stop and consider what you are doing. Odds are you are doing it wrong. Always code against the interface.

"var" saves some typing. Woopty-doo. With intellisense there are very few declarations that take more than three or four keystrokes anyway.

A Flurry of Voices on June 20, 2008 08:37 AM

Jeremy Grey et al:
I'm not misinformed on "var". "var" helps in the writing of code, but hurts the reading of code (or at least it does for me). The key to maintenance is reading code... other people's code (or your own, down the line). We all know how well coding guidelines work, especially when the people writing the code aren't on your team.

var x = SomeObject.SomeMethod();
What type is x? If I'm in the IDE I can find out (with extra work). If I'm in a text file or an email or a netmeeting or an HTML page or anywhere else I have no idea what that is.

I'm using a statically typed language in part because I can easily know what type of a variable is. This hides that.

Craptaculus on June 20, 2008 08:50 AM

> mylist is now a List. It can only be that and will only ever be that. But the only thing I ever do to mylist is to enumerate it. The best practice here would have been to declare it as:

Er... no. Just change "new List" into "new SomethingElse" and the compiler will reinfer your types, infer that "mylist" is now an instance of "SomethingElse" and check that all other uses are coherent with that. You fail.

And, in fact, a *smart* type inference system (I don't know about C#, but one along the lines of Haskell's) will be able not only to infer types (non-locally, to boot) but it will infer the most general types available. So in the case your talking about, it would even have inferred IEnumerable.

> In this case, using "var" has decreased the flexibility of your application in a subtle way. This method is now more rigid than it needs to be and will take more time in the future to modify.

It hasn't in any way, shape or form. Nice try, no sugar, you get an F.

> Always code against the interface.

How about "always code with your brain"? You've demonstrating that you're not thinking, only parroting things you don't get. Maybe you should pause for a second and try to get smarter than your IDE.

masklinn on June 20, 2008 08:50 AM

I have to say as a C++ and then/also C# programmer I've always been a little frustrated by the way in which objects are initialised... and the plethora of special purpose objects (e.g. StringBuilder) which are of questionable value. (would providing an 8-bit ANSI char type really have made the language any worse to use? really? made it better maybe?) I think c# tries to hard to be high level...

I have nothing against static typing though... although I find it odd that a more hybrid approach hasn't become the standard. afaik compilers always have enough information to do these sorts of "parlour tricks" and even better things... its a lot of code though, at least in my experience.

.NET has a base object type too... makes it even easier to do. :)

Jheriko on June 20, 2008 08:53 AM

> And it is a misuse because it goes against the opinions of the language designers.

In the future, I will thank you to please speak for yourself, not for me. You don't know what I think and it is presumptuous and offensive to claim that you do.

I agree with Jeff; removing valueless but hitherto required redundancy is a good thing.

Of course this feature can be misused to create code that is harder to read, understand, and maintain. All language features can be so misused; please refrain from doing so.

Finally, Jeff, I believe that you are somewhat conflating implicit/explicit typing (a LEXICAL characteristic of a language) with static/dynamic typing (a SEMANTIC characteristic of a language). Adding more implicit typing to C# does not move it in the direction of dynamic languages; adding dynamic typing moves it in the direction of dynamic languages.

Eric Lippert on June 20, 2008 09:07 AM

I'm with Dare on this one. Using var everywhere may be more convenient when you're cranking out code, but it doesn't express your intent to yourself, the compiler, and most importantly the next poor guy who has to dig through your code just to try to understand what variable types you're actually using.

Jon Galloway on June 20, 2008 09:11 AM

This is VB Developer speaks in you :) and I hear "VB vs. C#" tones more than I hear "Ruby vs. C#".
What about abstracting classes up? Like TextWriter writer = new StringWriter(). From my point of view, the "var" in its current state is just a useful half-way house for raw types which should be converted to the static types and better sooner than later. Code should be consistent and I pity those who will be maintaining the var-static-mixed code.

Michael Goldobin on June 20, 2008 09:29 AM

I haven't read all the comments (too lazy ...) but isn't most of our time taken up thinking rather than typing? Is it really such a big win to type var (or not) instead of a class name? Lots of people complain about verbosity but from my experience the syntactic 'noise' just disappears from my radar when I read code.

Bedwyr on June 20, 2008 09:37 AM

Jeff, I hope you won't regret this post in a few months/years ;)

Igor Brejc on June 20, 2008 09:38 AM

masklinn:
Calm down. I think you might be misreading what "A Flurry of Voices" said. By using "IEnumerable mylist" instead of "var mylist", the intent in much clearer (I'm going to be looping over it), and the code that uses "myList" will be easier to modify later because it is defined as "IEnumerable". If you just say "var", the "looping over" intent is not displayed. So, when someone (or you) comes to modify it later, it'll take you longer to figure out why you can't just change it to "new SomethingElse".

Yes, the compiler and IDE will catch it, but it's still extra work compared to simply typing out the interface name and thus your intent.


Also, for your advanced inference system: IEnumerable is an interface, and classes can implement many of them. If a class also implements IEnumerator, what is the type of the variable? Yes, the compiler and IDE knows, but does the guy reading the code?

A sufficiently advanced compiler/parser can infer that IEnumerable is the lowest common interface (or class) for all uses of the variable (ie foreach), but the poor guy modifying your code now has to figure out all the implications of adding another use of the varaible. If he adds passes the variable to a method which accepts a List, does the type change? *Can* he even pass it to the method? The only real way to tell is to try it and let the IDE or compiler tell him.

There's nothing wrong with that in Ruby, Perl, or Haskell, but I choose C# because the intent of code is much clearer. This doesn't help readability.

Craptaculus on June 20, 2008 09:39 AM

"Anything that removes redundancy from our code should be aggressively pursued -- up to and including switching languages."

Agreed. And without naming any names, the only languages that I've seen able to do this completely are those where code-is-data, and with a solid metaprogramming facility for generating code at read/build-time -- because those allow you to manipulate anything you wrote in any way.

Every nontrivial program I've ever worked on, in a language with a strict separation of code and data, has always ended up with repeated logic in slightly different forms. Sure, in all cases it's technically possible to extract the common functionality, but without built-in code-generation facilities, it's more work than just inlining each case. C programmers who need to both read and write a data file tend to write one function to read, and one function to write.

tc on June 20, 2008 09:41 AM

Bedwyr, I totally agree. My time is in thinking, not my typing.

To top it off, my thinking is a lot easier if I've spent the time writing and reading explicit code, I will therefore always fully declare everything if I can.

Explicit typing is a major reason I am a fan of C# and not VB / Javascript, etc.

The reason for "var" is it is a requirement to make the most of generics, extensions and linq.

I think they're all great features in the language but my gut feeling is that a lot of people are going to use them without enough thought and cause a lot of headaches further down the line.

Robin Day
http://www.advorto.com

Robin Day on June 20, 2008 09:51 AM

I find it amazing how slowly C# is adopting these features, it is really turning out to be the 'plumbing' language, i.e the language you code to the database with, but leave the business layer up to a more 'agile' CLR language like F# or Iron Python.

Example: The Magnificent language BOO (mentioned already in the comments) has had this from the start, and more besides. It's a true, first class CLR language, that looks like and more importantly programs like python.

In anycase I like to think about the problem space while I type, not the laborious syntax and always having to satisfy Intellisense and Resharper, so these features are welcome.

Andrew on June 20, 2008 09:59 AM

I must say that I'm not a big fan of dynamic typing. It just has too much capacity for abuse. I put this in the category of "goto" which, although perfectly valid to use, can lead to confusion and code that is difficult to maintain.

For instance, what would you make of this:

var myval = b.DoSomething();

what is myval? What methods does it support? What methods can I pass it in as a parameter? Can I use it in a printf() format? With intellisense, I probably can quickly find that out, but if I'm reading this code in a diff tool or other text editor, that won't be available.

Steve on June 20, 2008 10:07 AM

I disagree.

1. var url = "<a href="http://tinyurl.com/5pfvvy">http://tinyurl.com/5pfvvy</a>;";
2. var maxentries = 5;
3. var pi = 3.14159;

1. string or url? is it obvious? no.
2. int or long? is it obvious? no.
3. float or double? is it obvious? no.

See, the problem is that it may seem obvious to you what the variables should be, because you can see the whole picture and the intent for those variables (and potentially, what their future values will be) but the machine... it may end up having to cast to a new variable type.

I'm all for doing less typing (ie. work) but I'm a big fan of "say what you mean and mean what you say." That includes declaring variables. Why bother being ambiguous and expect some compiler that you didn't make figure it out what you mean. (Because if you didn't write it, it doesn't work... remember?)

Steve-O on June 20, 2008 10:09 AM

Scala does a really, really good job at local type inferencing. The beautiful thing about its type system is that types are usually optional (but not always).

def means method or function, calculated every time.
val means a value that will not change.
var means a value that might change.

val x = 1
var y = 12

With Scala's declarations you can optionally annotate with type.

val reader = new BufferedReader
var reader: Reader = new BufferedReader

Local type inferencing becomes dramatically more important to library authors who want really good, really precise typing on their public APIs. Type bounds and so forth can become pretty nasty to deal with from the library writer perspective, and type inferencing can make the resulting code dramatically easier to write.

There's always a tradeoff between very explicit code and commonly understood elements.

ArrayList<Reader> readers = new ArrayList<Reader>();

or

val readers = new ArrayList[Reader]

Having inferencing work for you during tuple operations is also a necessity for legible code.


Ross Judson on June 20, 2008 10:25 AM

Looks like my type annotations were removed for being HTML-ish. ;(

Ross Judson on June 20, 2008 10:31 AM

Agree with Steve-O on this being bad:

1. var url = "http://tinyurl.com/5pfvvy";
2. var maxentries = 5;
3. var pi = 3.14159;

This is a step backwards.

If you're complaining about C/C++/C# syntax in general, I agree. VB.NET is better, and Pascal is pure beauty.

A pet peeve of mine: people who use 'name' and an instance variable of class 'Name'. Off with their fingers!

Steve on June 20, 2008 10:34 AM

To Nicholas Paldino:

It does seem like it would be better to have the compiler infer the type from the LHS like your example:
MyObject m = new();

But I can't agree with you that all of us "got it wrong", because C# doesn't work that way. We have to make the best of what we've got. Personally I think the blog post got it right for the first set of examples, but wrong for the last set of examples.

Ideally the type should be written out in the code exactly once when declaring a new variable and instantiating an object of that type in the same line of code - for maximum readability, maintainability, and safety.

Tom on June 20, 2008 10:43 AM

masklinn had it correctly: too many inbred morons. Jeremy Gray's comment is also worth reading.

One observation (among too many, but some of them have already been made by the two I mentioned above):

---
var i = 1;

is i an int, a uint, a long, a short, an int32, int16, int64?
---

It's an int, idiot. Learn your language. Or, as a faster alternative, use Resharper and write

int i = 1;

It will inform you that you CAN, if you CHOOSE, change that to

var i = 1;

It will NOT do that if you had typed

short i = 1;

in the first place.

Ah. I am trying not to ignore that these people pretend to be programmers.

Marcel Popescu on June 20, 2008 10:44 AM

Oops. Typo. I am trying TO (delete the "not") ignore that these people...

Marcel Popescu on June 20, 2008 10:45 AM

var is useful and the confusion can be easy avoided

first of all: the difference between int and long? yeah? in which C?
you use float instead of double? why?
there are 8 types of integers (including signed/unsigned and not counting long), 2 (theoretically 3) real types and no equivalent for sql money? whatever.

an language must help the programmer (at least their expectations :), so when you type:

var i = 2;
var x = 3.14;
var c = 'a';

90% you will expect/want/need
int 32b signed i
double x
char signed c

want unsigned int? var x = 3u; or var x = uint32(3);
float? var a = 3.14f; or var a = float(3.14);
and so on...

about pointer to 0... NULL == 0 ? big mistake,
NULL should be (void *)0


fane on June 20, 2008 10:48 AM

This kind of article makes me lower my opinion about the quality of your analysis.

This is one step further bad coding practices, it will make reading code more difficult and will be more likely to hide errors. C# was clean, they are making it look more like VB which is a shit language.

I think you just jumped the shark to me.

Fab on June 20, 2008 10:52 AM

@Andrew

"I find it amazing how slowly C# is adopting these features,"

Then again, look at java. Compared to it, C# is adapting at a blazing speed. I'll bet a lot of this has to do with the existing code base. if you Microsoft or Sun, you can't just change everything to the latest & greatest whenever you want to, whereas when designing a new language from scratch, you can!


I attended a "What's new in C# 3.0" session at Austin.net CodeCamp a month or so ago, and I doubt there was a person in that (very full) room that didn't rejoice about this new feature. But, as with any other language feature, you, the programmer, need to be aware of what it does and use it when appropriate.

One of the other new C# features I love even more than this is automatic properties!

Dennis on June 20, 2008 10:53 AM

I am all about concise code, but this syntax is necessary for OOP and polymorphism. Allowing stuff like this:

public BaseClass obj1 = new ExtendedClass1();
public BaseClass obj2 = new ExtendedClass2();

if(obj1 > obj2)
DoSomething();

Is the compiler smart enough to make this work with var?

Jesse on June 20, 2008 10:56 AM

@Daniel Lehmann

> If the constructor call fails, the variable will not be assigned and your "Catch" will also fail. You should always call the constructor BEFORE the "Try".

Correct, the constructor will fail and the object will not be instantiated, but you still have access to the variable. So you would have to check if the object was created (check for Nothing) before trying to access any properties or methods, but the variable is at least in the scope of the routine outside of the try block.

Dave on June 20, 2008 10:58 AM

Based on some of the comments I've read, it seems you stroke a chord here, Jeff. I, like you, think conciseness goes a long way in code clarity. It is, though, a topic marred by conflicting points (ranging from technical difficulties to personal preferences).

I believe PHP code is a breeze to go through (most of the times, of course -- and provided a decent coder was cognizant of the future pain of his/her successor). Can you honestly say this is not as clear as you can possibly get?

$result = mysql_query($query);

NOTE: I'm not a PHP lover. I'd pick Java any given day. However, you can't deny it is easier, and faster, to read code written in PHP (and, arguably, write) because of this simple fact.

NOTE 2: This comparison also neglects the fact that both languages are very different since they were created to tackle dissimilar problems.

Elvis Montero on June 20, 2008 11:07 AM

One line:

string hash = FormsAuthentication.HashPasswordForStoringInConfigFile(string txt);

Yes, this is built into .NET--and I think it says pretty much everything that needs to be said about this problem. :)

On a side note, the equivalent PHP functions are named md5() and sha1().

WesleyC on June 20, 2008 11:13 AM

I'm sure this all so very yawn-inducing for PHP developers.

Mattkins on June 20, 2008 11:19 AM

Marcel Popescu:
| var i = 1;
| is i an int, a uint, a long, a short, an int32, int16, int64?
| ---
| It's an int, idiot. Learn your language

Yikes, such venom. The point is: if I'm reading this code which someone else wrote, am *I* sure what was intended? Am *I* sure that the original programmer meant an int? Will "var i" overflow if I change a while loop? Will "var i" overflow if I change an input condition? Yes, the compiler knows. Yes, as I read the code I can examine the right-handside and say "oh, '1' means that 'i' will be an int" but that's much less clear and takes longer than just typing "int" in the first place, especially since that is what the programmer (presumably) intended.

Also, what if it's a expression or a method call on the right-hand side? The insults and calls to "Learn your language" don't help much, then.


Craptaculus on June 20, 2008 11:34 AM

@Craptaculus
> There's nothing wrong with that in Ruby, Perl, or Haskell

Please, just stop posting, the rest of your post is tripe and retardation but this takes the cake. Ruby and Perl are two dynamically typed languages and have no relevance *whatsoever* in the discussion, and Haskell is more statically typed than C# could ever dream to be with a type system of a richness C# couldn't achieve in a million years.

masklinn on June 20, 2008 11:44 AM


IMHO, and this has probably been said, the simple facts are:

1. "var" (or "auto" or "dim") is a huge time-saver over repeating the variable type in most cases.
2. NOT having "var" (etc) as a signifier of "this is a new variable" means that the simple typo (the #1 flaw in most code which hasn't been sent to a compiler) doesn't get caught by the compiler and results in a very hard-to-find bug. I've worked in a language like this extensively (4th Dimension), and mistyped variable names are a key common programmer error which cause major disturbances.
3. There needs to be a way to declare that you are seeing a particular instance of an object "as" something else (ex, the "BufferedReader" as a simple "Reader") primarily for future code purposes (ex, you know now that it can only be a BufferedReader but in the next sprint you'll be getting the input as a StringReader instead), although also conceivably for current code purposes (it is declared by setting it to a BufferedReader, but you have a conditional right below which resets it to a StringReader if it's a Monday before autumnal equinox); will the compiler be smart enough to cast down to the right level so that all assignments work while keeping all uses working as well?
4. The ability to simply search for "var" (etc) to find all variable declarations is really nice. I too miss that with C and Java.

IMHO, the cure for 3 and 4 is that the cases where auto-classing will NOT work should instead use a syntax like:

var as Reader reader = new BufferedReader ( ... );

Tom Dibble on June 20, 2008 11:54 AM

mmmm... syntactic sugar... *gurgling*

Ryan Ische on June 20, 2008 11:59 AM

Jeff, I like "var"-style type inference (and I'm glad you're posting about programming again), but you dropped the ball at the very end there. Static type inference has nothing to do with dynamic typing. Dynamic typing is bad for the reasons Grandpa Coder listed above (which basically boil down to "dynamic typing means delaying your error-checking until testing and deployment, rather than compile time"), but "var" does not have those problems. It's just syntactic sugar for the same old static type system C# has always had. Which is a good thing.

Of course "var" can be misused and overused. It certainly shouldn't be used in cases like "var i = 42", where it promotes confusion without even saving keystrokes. But it's a great bit of syntactic sugar that can make code more readable, if it's used correctly.

Anonymous Cowherd on June 20, 2008 12:02 PM

Hmm...

An error occurred:

Rebuild failed: Renaming tempfile 'C:\codinghorror\blog\archives\001136.html.new' failed: Renaming 'C:\codinghorror\blog\archives\001136.html.new' to 'C:\codinghorror\blog\archives\001136.html' failed: Permission denied

Anonymous Cowherd on June 20, 2008 12:06 PM

Wow masklinn, you still haven't calmed down, and you have the almost magical ability to completely misread what is written. I'm perfectly aware of the nature of those languages, and I fail to see what your comments have to do with what I was talking about (you'll have a witty^H^H^H^H^H rejoinder for that, I'm sure).

> Please, just stop posting

Ummm, yeah. How about you just skip reading them instead? You don't seem to have the knack for it anyway.

Craptaculus on June 20, 2008 12:07 PM

masklinn -

Is there a reason virtually all your posts have been abusive to people who disagree with your point of view? I enjoy coming to this site, but if the level of discourse is reduced to namecalling, I really don't think I'll bother in the future.

gregs on June 20, 2008 12:09 PM

I absolutely disagree - explicitly declaring your type is very important when dealing with object-oriented programming. Example:
class Foo {}
class Bar : Foo {}

var f = new Bar();
f = new Foo();
// this will not compile, since f is typed Bar, not Foo.

When reading code, I much prefer the old-fashioned way.

"var" does have its uses. It's great for the new features of C#, like anonymous types - I'm using it when working with binding a small amount of data to a web page - the data object can be an anonymous type, as long as the property names match up to what's evaluated on the control.

Joe Enos on June 20, 2008 12:45 PM

I agree that this neat compile-time trick aids readability of the code. But as several people indicated already, the "var" syntax cannot be used to handle cases where you want to use a base class pointer.
Of course, one can argue that these types of assignments often happen in factories, so in the end there is no problem using the var syntax:

var p1 = Factory.Create("Employee");

where, Factory.Create() has a return type of Person (the superclass of Employee).

Mohammad on June 20, 2008 12:47 PM

Man, you grew up on BASIC, so why are you questioning this bullshit now? Tons of languages have redundancy problems, but not VB. Instead of catechizing the verbosity of C#, why don't you just use a language that....

a) You are more familiar with
b) Is used by more programmers
c) Has been around longer
d) Is easier to read (remember, code gets read many times, written once)
e) Is better overall

I'd like an honest answer as to why you would even want to mess with C# on this project. Here's my take: if you ever have to "refactor" variable declarations, you've FAILED by using an inferior language. Oh, and nice one-letter variable names too, loser!

Sorry, but this was a lame post.

Josh Stodola on June 20, 2008 01:19 PM

@Tom Dibble
> var as Reader reader = new BufferedReader ( ... );

I found Scala had quite a nice syntax there:

val reader:Reader = new BufferedReader();

with the ":type" being optional (to leverage the type inference system)

Haskell is also fairly interesting in that it separates the type declaration from the initialisation itself:

let
reader :: Reader
reader = bufferedReader
in whateverExpression

> Is there a reason virtually all your posts have been abusive to people who disagree with your point of view?

They haven't, I have no problem with people who disagree with me. I do on the other hand have a problem with people who don't know anything about the subject, conflate type inference and dynamic typing and overall don't have any idea of the subject but still disagree with the option.

masklinn on June 20, 2008 01:19 PM

@Joe Enos
> var f = new Bar();
> f = new Foo();
> // this will not compile, since f is typed Bar, not Foo.

That's absolutely not a given. As I mentioned, I don't know how smart C#'s type inference system is, but several type inference algorithms are able to look for and use the most general type possible.

In this case and unless you're using features specific to the Bar type (or returning f and asking for a Bar return value), in which case the program rightfully shouldn't be accepted by the compiler (as it'd be incorrectly typed), there is no reason why the compiler couldn't infer f as being of type Foo.

An example I quite line is that of Haskell, where "5" (without any context that would add type constraints to it) infers not to "Int", or "Integer" but to "Num", which is the highest type in the numerical hierarchy (and a completely abstract type).

masklinn on June 20, 2008 01:27 PM

Why is it that the programmers that use these obscure, unpopular languages have to get so defensive about everything, all the way down to which language _declares variables better_!! Geeze...

HB on June 20, 2008 01:32 PM

Jeff,
I have to say I disagree with this advice.The var keyword I believe is great for LINQ and anonmyous types but it will reduce readability and most importantly intent in the source code if its overused everywhere.

o.s. on June 20, 2008 01:39 PM

As an avid c# fan and general Microsoft technology enthusiast, as soon as I saw "Anything that removes redundancy from our code should be aggressively pursued -- up to and including switching languages." in an article about removing redundancy that references a feature in c# (a language developed by Microsoft), all I could think was "This guy just opened up the flame gates".

I admittedly didn't read all the comments to verify, but I did do a quick word search across the comments, and at the time I'm writing this, I see 7 instances of the word "ruby", 5 instances of "python", and 4 instances of "scala". Some may be quoting others and creating redundancy, but still, all 3 of the languages that spring to mind when I think "evangelism" are represented.

Alex on June 20, 2008 01:39 PM

(quote)
StringBuilder sb = new(256);
UTF8Encoding e = new();
MD5CryptoServiceProvider md5 = new();
(/quote)
Or in C++, as they don't escape the function they're used in:
(quote)
StringBuilder sb(256);
UTF8Encoding e;
MD5CryptoServiceProvider md5;
(/quote)
Though for parameterized types or dynamic allocation, C++ gets verbose. typedef lets you reduce that if you are using the same type over and again - typically you only have a single parametric nesting:
class Foo;
typedef ref_ptr<Foo> FooPtr;
typedef std::vector<FooPtr> FooVector;

FooVector some_foos;

rather than
std::vector<ref_ptr<Foo> > some_foos;

In terms of strong typing (as opposed to what's supplied by C++, though you can make the bear dance if you want) I'd like to be able to annotate constructs with constraints rather than having to push the type system to do it, and have something like ESP|http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.15.3759 for the checks.


Though discussing developer productivity is more a human question than a language one. About half the projects I've been in on have non-development tasks as their critical path. Developers in big companies like C++ because it means you can justify spending time writing code, and you're doing something you enjoy. If you make the coding ten times more productive, it means you spend 99% of your time in meetings or hassling another section of the company to get the requirements documentation to pass gate D sign-off instead of 90%. Yay.

Pete Kirkham on June 20, 2008 01:48 PM

I agree everywhere but the floating point. I want that extra control over percission.

I suppose that if it did not matter, it might fly, but I rarely find it does not matter.

Xepol on June 20, 2008 01:54 PM

Jeff, usually I agree with you but not on this. I'm sure it's been said above but I want to add my voice to the anti-var crowd. Sure, the original code may be redundant, but it is also clear, straightforward, and unambiguous.

Some of the biggest points of a strongly-typed language is to remove ambiguity and prevent errors. Cute "tricks" like var undermine all this.

Nick on June 20, 2008 02:09 PM

"You might even say implicit variable typing is a gateway drug to more dynamically typed languages. And that's a good thing." -- Jeff

"Some of the biggest points of a strongly-typed language is to remove ambiguity and prevent errors. Cute "tricks" like var undermine all this." -- Nick

Tell that to OCaml, which is very happily implicitly typed throughout, and whose exceedingly reasonable catches bugs that neither C#, nor Java, nor Ruby, nor Groovy can catch (like null pointer exceptions).

Implicit static typing is the wave of the future, not a half-hearted compromise with dynamic typing enthusiasts.

Robert Fischer on June 20, 2008 02:25 PM

"...catches bugs that neither C#, nor Java, nor Ruby, nor Groovy can catch (like null pointer exceptions)."

That's not true at all. I cannot speak for Ruby. But C#, Java, and Groovy CAN catch NullPointerExceptions. It's just that that type of exception is normally the least expected and a try-catch block is not written by the programmer to handle it.

As for masklinn (dick), you set yourself on a pedestal as coder supreme and treat everyone else as "uneducated retarded inbred morons". But your childish level of discourse reduces the intelligence of the entire conversation. You are socially inept and contribute nothing positive the conversation. The internet would be exponentially better without you and your masturbatory posts.

masklinn is a dick on June 20, 2008 02:39 PM

D'oh. Left out a couple critical words.

"...whose exceedingly reasonable *TYPE SYSTEM* catches bugs that neither C#, nor Java, nor Ruby, nor Groovy can catch (like null pointer exceptions)."

See my post "7 Actually Useful Things You Didn't Know Static Typing Could Do: An Introduction for the Dynamic Language Enthusiast" for that and other nifty stunts.
http://enfranchisedmind.com/blog/2008/04/14/useful-things-about-static-typing/

Robert Fischer on June 20, 2008 02:53 PM

"Don't need 'var' either. Of course it's a variable."

Seems like this is going in circles. I remember back when VB6 was what most business apps were written in and the fact that the compiler didn't make you specify when you were allocating a variable was seen as some great evil and one of the reasons VB was a "toy language".

I can see the argument for not using it when the type is clearly visible to the right side of the assignment, but still think I'll keep explicitly typing unless its a situation where var is required.

David Fauber on June 20, 2008 03:01 PM

"But your childish level of discourse reduces the intelligence of the entire conversation."
"masklinn is a dick on June 20, 2008 02:39 PM"

checksum failed

David Fauber on June 20, 2008 03:02 PM

When you mouse over the var it will tell you the type the compiler has inferred.

brian on June 20, 2008 03:07 PM

A much greater improvement in the latest C# is the ability to write anonymous functions in lambda form, especially in the context of generic collection classes.

If you have a generic (templated) collections, you already have substantial type information about each element and about the signature of functions on them, yet C# previously required you to use the delegate keyword and redeclare the type of the element in the function profile. In other words, assuming you have defined some
List<DescriptivelyNamedFoo> fooList = new List<DescriptivelyNamedFoo>();

where you previously had to write:
...
fooList.ForEach( delegate( DescriptivelyNamedFoo foo) { foo.LilBunny(); });
if ( fooList.Exists( delegate( DescriptivelyNamedFoo foo) { return foo.IsHopping; }) ) {
// must be in forest...
}

you can now write:
fooList.Foreach( (foo)=>{foo.LilBunny();});
if ( fooList.Exists( (foo)=>{ return foo.IsHopping; } )) {
// must be in forest...
}

etc. The delegate declaration overhead no longer grossly outweighs the function's typical body size.

Clifton Royston on June 20, 2008 03:07 PM

With statement completion each in a new class file so it has no hints.
Assuming the right namespace is already included.

24 keystrokes for:
var sb = new StringBuilder(256);

22 keystrokes for:
StringBuilder sb = new StringBuilder(256);

20 keystrokes for:
var e = new UTF8Encoding();

18 keystrokes for:
UTF8Encoding e = new UTF8Encoding();

22 keystrokes for:
var md5 = new MD5CryptoServiceProvider();

19 keystrokes for:
MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();

monkey on June 20, 2008 03:17 PM

Oh that's nothing! What are you complaining about?

At the job I just got...the boss doesn't even want to acknowledge that polymorphism exists! (He dropped out of college twice)...thus his c++ code looks alot like this:

if(strcmp(arg_string, "commandUno") == 0)
{
// Same code that is in 40 other blocks...aside from arguments.
}else if(strcmp(arg_string, "commandDose") == 0)
{
// Same code that is in 40 other blocks...aside from arguments.
}
else if(strcmp(arg_string, "commandTrace") == 0)
{
// Same code that is in 40 other blocks...aside from arguments.
}
else if(strcmp(arg_string, "commandQuadro") == 0)
{
// Same code that is in 40 other blocks...aside from arguments.
}
else if (strcmp(arg_string, "commandCincoDeeMayo") == 0)
{
// Same code that is in 40 other blocks...aside from arguments.
}
else if (strcmp(arg_string, "commandSas") == 0)
{
// Same code that is in 40 other blocks...aside from arguments.
}
// ...continue until you have 20 if statements....

I mean if we're going to revert to that, why don't we just write out our for loops too while were at it....?

int i = 0;
i = 1;
i = 2;
i = 3;
i = 4;
i = 5;
i = 6;
// ...

Ah, I mean it's bad enough he's still using C++ but my goodness!

His excuse for "not learning the right way to do it..." was that it makes the size of his executable grow from 2MB to 8MB!

My boss uses Intel Duo Core, 3.0GHZ with an excess of 4GBs of RAM on most of the computers he serves these off of!

I'm not the crazy one here right?

Anonymous Coward on June 20, 2008 03:19 PM

1. var url = "<a href="http://tinyurl.com/5pfvvy">http://tinyurl.com/5pfvvy</a>;";
2. var maxentries = 5;
3. var pi = 3.14159;

1. string or url? is it obvious? no.
2. int or long? is it obvious? no.
3. float or double? is it obvious? no.

And for every last one of these examples, does it matter? No.
For each, it's both. The only question is whether you want to use the extra functionality/size of the second option.
Surely this is one of those things we've been bludgeoned into accepting, no matter how many times it causes a problem. It's like being a victim of spousal abuse. "Oh, it's my fault there was an integer overflow, I forgot to cast the variable to a long rather than an int. The Compiler loves me really."
Why can't it handle the cast itself?

Tom on June 20, 2008 03:26 PM

What are you trying to prove by counting keystrokes? Eliminating redundancy in this kind of situation should not be about saving keystrokes. It should be about making the code more readable and maintainable.

Tom on June 20, 2008 03:31 PM

Tom

Not trying to prove anything, simply stating facts. In my opinion var is less readable, but readability is subject by nature. And I would suggest that the more explicit code is the easier it would be to maintain, but again that's just my opinion. If anyone has a measure of readability or maintainability that is not subjective I'd love to see it.

monkey on June 20, 2008 03:39 PM

@David Fauber

'Seems like this is going in circles. I remember back when VB6 was what most business apps were written in and the fact that the compiler didn't make you specify when you were allocating a variable was seen as some great evil and one of the reasons VB was a "toy language".'

I remember when the weak typing of Perl was considered a great win. And then it wasn't anymore, and Java's inheritance-based type system was considered the salvation of development. Then Ruby's dynamic typing was the key to its productivity. Round and round...