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.
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.
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 2:19 AM@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 2:19 AM@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 2:27 AMWhy 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 2:32 AMJeff,
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.
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 2:39 AM(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_ptrFoo FooPtr;
typedef std::vectorFooPtr FooVector;
FooVector some_foos;
rather than
std::vectorref_ptrFoo 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.
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 2:54 AMJeff, 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 3:09 AM"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 3:25 AM"...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.
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/
"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.
"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 4:02 AMWhen you mouse over the var it will tell you the type the compiler has inferred.
brian on June 20, 2008 4:07 AMWith 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();
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 4:19 AM1. 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?
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 4:31 AMTom
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 4:39 AMI 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 4:40 AM@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...
Robert Fischer on June 20, 2008 4:42 AMWhat do you mean by redundancy?
Niyaz PK on June 20, 2008 4:43 AMWhat do you mean by redundancy?
Niyaz PK on June 20, 2008 4:44 AM@Jeff Atwood
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?
Yes, for an entire class of apps, you would be better off using a simple, unbounded Number type, calculated and rounded using decimal rules instead of binary, so that math behaves like people expect it to. This is available in some languages, although they are "much slower" than native numeric types; although whether that's "too slow" is another question entirely.
But sometimes specifying the width/representation is a requirement or a distinct advantage (usually in size/speed).
Vandicov on June 20, 2008 4:51 AMThe new C++ standard (C++0x) seems to have moved towards this with "auto", so instead of this:
vectorstring::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 4:55 AM@Dave: If the constructor fails the variable will always be null and useless to you, so it is correct to not even have access to it.
Daniel Lehmann on June 20, 2008 4:57 AMI 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.
Amen! Now we just need to get rid of "var" ;-)
Andrew Peters on June 20, 2008 4:58 AMGets even worse with generics. Nothing like typing
MapString, MapLong, Point bla = new MapString, MapLong, Point();
J. Stoever on June 20, 2008 4:59 AMAgreed. 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 5:00 AMBleh, comment software ate my less than and greater than signs. One more try:
MapString, MapLong, Point bla = new MapString, MapLong, Point();
J. Stoever on June 20, 2008 5:00 AMSomeone 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
As one of the few, remaining C/C++ developers left - I think this is the worst idea in the world. Why? its completely non readable and makes maintenance a bitch. Being lazy is not a good thing! Don't be a lazy programmer!!
end rant
Justin on June 20, 2008 5:06 AMAlso,
myEvent += new MyEventHandler(myEventHandler);
can be reduced to:
myEvent += myEventHandler;
Any particular interest to "Judy York"?
url = "http://tinyurl.com/5pfvvy";
“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 5: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 5:26 AMYes, 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 5:27 AMDon't need 'var' either. Of course it's a variable.
izb on June 20, 2008 5: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 5:28 AMWhat 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.
what about when you want to do this
1: StringBuilder sb
...
100: sb = new StringBuilder(....)
I think it depends on your background, I prefer knowing that my objects and variables are well declared and aren't going to change type dynamically.
mauro on June 20, 2008 5:32 AMThe 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 5:34 AMThat's one of the reasons I hate Java.
Tiago on June 20, 2008 5:37 AMDamn, 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 5:41 AMDon'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 5:42 AM@Niyaz PK
LOL, that was quite funny....
Carl on June 20, 2008 5:42 AMAlways 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 5:42 AMThis is actually the first time I have come to disagree with you. I agree with the many previous posters who mentioned about the ambiguity over class hierarchy. Ex: SuperClassOfClass c = new Class();
I am always a fan of explicit code because it tells me more about every created object saving the guesswork regardless of how much easier to type it is. On longer projects I can forget what lines of MY OWN code is for, let alone the code written by someone else.
Then again, I'm only a student still...
Dave N on June 20, 2008 5:42 AMDeclaring 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.
Comon Jeff, learn some haskell, ml, lisp, then write articles about programming languages and compiler tricks.
Ramnas Gutkovas on June 20, 2008 5:44 AMI 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 5:45 AMI 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 5:51 AMMoreover, 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.
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 5:55 AMI 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.
1. var url = "http://tinyurl.com/5pfvvy";
2. var maxentries = 5;
3. var pi = 3.14159;
1. string or url? is it obvious? no.
Actually, it is obviously a string. If you wanted to make it a URL type, you would do something like this: var url = new URL("http://tinyurl.com/5pfvvy");
2. int or long? is it obvious? no.
3. float or double? is it obvious? no.
When should you care?
When you're writing video drivers and wringing every last femtogram of performance out of the hardware, that's when. But you'd be using C for that.
In other situations, it's OK to use a language where you don't have to micromanage numeric types.
Learning what types are assigned to immediate values hasn't proven to be much of a problem for any of the popular dynamic languages.
Josh on June 20, 2008 6:00 AMI'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 6: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 6:06 AMSidenote: 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 6: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 6:07 AMFor simple examples this might be easier, but what about functions that have return values?
var foo = Foo.Bar();
Not very clear what type foo is. Now you have to take the extra step of trying to use foo or hovering over Bar() to find out from intelisense what the type is.
I'm a big fan of consistency over saving a few characters of decleration.
You also want to be more explicit when working with higher level design patterns which are all based on interfaces and subclasses.
Jim Greco on June 20, 2008 6:08 AMActually 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 6:10 AMIt 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" :-)
Yuk. I hate cleaning up code that's not strictly typed. This stuff is hard enough to make work. Every programmer should wear handcuffs and be required to explicitly type and comment everything.
If programmers had write their own paychecks they wouldn't write that one-way write only crap code. They would write beautiful code because they never know when they'll be waist deep in it again.
var = crap
Mr_Simple on June 20, 2008 6:14 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 6:16 AMI 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 6:20 AMIndeed, 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 6:26 AMIMO Var opens up the possibility of incredible messes and maintenance hell, all to save half a second of typing. Is it really worth using it?
Ryan on June 20, 2008 6:27 AMTaking 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();
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.
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 6:34 AM 1. var url = "http://tinyurl.com/5pfvvy";
2. var maxentries = 5;
3. var pi = 3.14159;
1. string or url? is it obvious? no.
Yes, it is a string.
2. int or long? is it obvious? no.
Yes, it is a int. A long would be written as "5L"
3. float or double? is it obvious? no.
Yes, it is a double. A float would be written as "3.14159f"
So I disagree that the declarations are unclear, but I would probably still explicitly declare the type for primitives.
Marc on June 20, 2008 6:36 AMYou should give Python a shot - you don't have to deal with any of this unnecessary verbosity.
Guido van Rossum on June 20, 2008 6: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.
var is just about as useful as Option Strict Off...
Calvin on June 20, 2008 6:50 AM@masklinn:
Regarding the Foo/Bar example - I agree that the compiler should realize that I'm not calling any Bar-specific stuff, but it doesn't. Trying to compile that example fails.
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 6:57 AMUgh! 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 6:58 AMVar 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 7:00 AMFeepingCreature 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 7: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 7:10 AMI 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 7:12 AMAmen Grandpa Coder!
JohnM on June 20, 2008 7:14 AMIt 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 7:15 AMNot 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.
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 7:20 AMDunno 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 7:30 AMMuch of the time I'm using interfaces. For example in C#:
IDictionarystring, string myDictionary = new Dictionarystring, string();
Or in Java:
MapString, String myMap = new HashMapString, 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 7:32 AMCan 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#:
IDictionarystring, string myDictionary = new Dictionarystring, string();
Or in Java:
Mapstring, string myMap = new HashMapstring, 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 7: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 7:42 AMAnd 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 7:42 AMAm 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 7:43 AMUgh! 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 7:44 AMI'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 7:44 AMThe 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.
@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.
(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 7:47 AMThe comments to this entry are closed.
|
|
Traffic Stats |