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.
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 3:40 AMWhat do you mean by redundancy?
Niyaz PK on June 20, 2008 3:43 AMWhat do you mean by redundancy?
Niyaz PK on June 20, 2008 3:44 AMThe 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 3:55 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 3:58 AMGets 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 3: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 4:00 AMBleh, 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 4: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
Also,
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 4: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 4: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 4:27 AMDon't need 'var' either. Of course it's a variable.
izb on June 20, 2008 4: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 4: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.
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 4:34 AMThat's one of the reasons I hate Java.
Tiago on June 20, 2008 4: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 4: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 4:42 AM@Niyaz PK
LOL, that was quite funny....
Carl on June 20, 2008 4: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 4: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.
Ramūnas Gutkovas on June 20, 2008 4: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 4: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 4: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 4: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.
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 4:59 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 5: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 5: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 5: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 5:07 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 5: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" :-)
(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 5: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 5: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 5:26 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 5:34 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 5: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.
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 5: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 5: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 6: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 6: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 6: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 6:12 AMAmen Grandpa Coder!
JohnM on June 20, 2008 6: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 6: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 6: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 6:30 AMMuch 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 6: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#:
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 6: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 6: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 6: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 6: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 6: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 6: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 6:47 AMI 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 6:48 AMBesides ... usually by typing 2 or three characters I can hit tab and get the declaration I want anyway.
N on June 20, 2008 6:48 AMI 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 6:48 AMJust a thought.. why not remove the keyword var also?? So instead of var v = new myobject() v = new myobject()
paramesh on June 20, 2008 6: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 6: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 6: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 7:04 AMHow 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 7:06 AMWhat 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 7:09 AMDuh... 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!
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 7:12 AMJust 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 7:14 AMTo make it simpler, the declaration of the variable should be the popup tooltip when hovering over the variable name.
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 7:15 AMHi 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 7:18 AMI'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 7: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 7:31 AMI 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 7: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 7:36 AMI 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 7:41 AMvar myReader = new Reader() is unambiguous
However
var pi = 3.1415 is ambiguous (is a decimal? float? double?)
Wile_E_Coyote on June 20, 2008 7:50 AMAnother 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 7:51 AMAnyone 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 7:53 AMHere'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 7: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 7:55 AMI'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 7:55 AMI 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 7: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 7:57 AMI 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 7:59 AMUnfortunately, 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 8:00 AMIn 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 8:06 AMExcept 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.
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 8: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 8:23 AMThe 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 8:24 AMI 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.
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 8:28 AMJeff:
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 8:29 AMI 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 8:32 AMUsing 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 8: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 8: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 8:50 AMI 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 8: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.
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 9:11 AMThis 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.
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 9:37 AMJeff, I hope you won't regret this post in a few months/years ;)
Igor Brejc on June 20, 2008 9:38 AMmasklinn:
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.
"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.
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
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 9:59 AMI 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.
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 AMScala 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.
Looks like my type annotations were removed for being HTML-ish. ;(
Ross Judson on June 20, 2008 10:31 AMAgree 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 AMTo 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 AMmasklinn 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.
Oops. Typo. I am trying TO (delete the "not") ignore that these people...
Marcel Popescu on June 20, 2008 10:45 AMvar 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
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 AMI 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.
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 AMOne 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 AMI'm sure this all so very yawn-inducing for PHP developers.
Mattkins on June 20, 2008 11:19 AMMarcel 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
> 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 ( ... );
mmmm... syntactic sugar... *gurgling*
Ryan Ische on June 20, 2008 11:59 AMJeff, 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 PMHmm...
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 PMWow 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.
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 PMI 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 PMI 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 PMMan, 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 1: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 1: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 1:27 PMWhy 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 1:32 PMJeff,
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 1: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.
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 1:54 PMJeff, 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 2: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 2: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.
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 3:02 PMWhen you mouse over the var it will tell you the type the compiler has inferred.
brian on June 20, 2008 3:07 PMA 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 3:07 PMWith 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 3:19 PM1. 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 3:31 PMTom
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 3: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...
Robert Fischer on June 20, 2008 3:42 PM@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 3:51 PM@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 3:57 PMAs 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 4:06 PMwhat 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 4:32 PMThis 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 4:42 PM> 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 5:00 PMFor 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 5:08 PMYuk. 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 5:14 PMIMO 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 5:27 PMDid we learn nothing from VB and it's Variants?
Aaron on June 20, 2008 5:30 PM> 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 5:36 PMvar is just about as useful as Option Strict Off...
Calvin on June 20, 2008 5:50 PM@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.
Well if only now you could eliminate the left over redundancy of, well "var" itself, we'd be in business.
What do you need to know its a var, when the parser hits text, thats not in the symbol table, its a var. Yes it makes the compiler less efficient, but us being faster, is a good trade off.
Chris on June 20, 2008 7:20 PMIf keeping declarations short helps with readability, then I'd propose limiting all the variable names to six characters and adopting a convention where integers have names starting with the letters I through L and everything else is assumed to be a REAL. (Or you could just go to www.lahey.com and buy a Fortran compiler. I believe they have one for .Net.)
My problem with this scheme is that the style for declaring variables isn't consistent. Sometimes you declare ComplexObjectType as ComplexObjectType (e.g. when it's coming from a factory), sometimes you declare it as a var because ComplexObjectType will appear on the right side of an equal sign.
This leads to some mental gymnastics when you're deciding which style to use, and more gymnastics when you go to maintain the code six months from now.
Worse, when a junior coder comes along and sees this abuse of the anonymous type, [s]he might not realize the conditions of the coding style. Then you end up with something like
var object = Server.Create()
because the junior person simply didn't know better.
I agree, typing something like
MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
seems needlessly verbose, but if you're using Visual Studio (or, I'd hope, pretty much any other IDE) Intellisense is going to kick in and type everything after the new for you.
IMHO, the minimal time savings from using the anonymous type isn't justified when you compare it to the maintenance hassles.
Blair on June 20, 2008 7:56 PMThe more I think about it, and the more examples I see, the more I think _var_ was a terrible mistake.
This is doubly so for people who are insane enough to advocate eliminating even the _var_ keyword. Suppose you have a large class. In a method you have the line:
actionResult = false;
Is that a declaration/initialization or an assignment? What's the scope of that variable? Depending on an IDE to tell you these things is a language fault and overly shortsighted.
But hey, just my opinion. I'll keep writing clear, readable, and unambiguous code.
Nick on June 20, 2008 7:57 PMinstead of "StringBuilder sb = new StringBuilder(256);" or "var sb = new StringBuilder(256);", I would prefer "StringBuilder sb = new (256);" - you get the variable type explicitly declared, and the constructor implicitly. Seems a lot safer. In the case where you need an abstract base variable with a concrete type, you'd obviously define the concrete type after new, as per usual.
f0dder on June 20, 2008 8:16 PMImplicitly typed local variables on C#? Ok
It just made me wonder how you compared PHP as a mess of functions and how organized is C#. Btw, the idea of listing the functions in php that starts with 'a' was taken from a video of the guys from Django. Right?
Anyway, I guess this video is really nice and pertinent to C# version 3
http://www.railsenvy.com/2007/10/9/ruby-on-rails-vs-net-2
nice comedy ;)
Ow, and your blog and the podcasts with Joel Spolsky are really nice.
Best Regards from Brazil
Dani Berg on June 20, 2008 8:24 PM[quote]
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
[/quote]
Amen :-) I've been doing Python for two years now, and this has never been a problem whether I'm writing new code or maintaining someone else's. Python Just Makes Sense (TM) ;-)
astigmatik on June 20, 2008 8:33 PMI'd like to paraphrase Steve McConnell here (or whoever he was quoting):
Code for people first; compilers second.
To the compiler, it doesn't matter whether you use var or IEnumerable<List<T>>, it all looks the same.
To a person, however, the latter is much clearer.
TraumaPony on June 20, 2008 8:52 PMOh, and the people using the example
"var pi = 3.14159: float or double?"
If you know anything about C#, you'll know it's a double ;)
Really strange that things long implemented are raising such an interesteed if re-implemented in C# or Java. How about a look at any decent functional programming language?
And well, even with some Oldtimer like Smalltalk one can write
foo := Foo new
.....
I'm sorry but the whole explictly needed static type declaration stuff is so 80ies ;-)
Have fun with C++ templates
std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char,
std::char_traits<char>, std::allocator<char> > > > variable = ...
Hi Jeff --
Joel explained this very well on the show -- but i don't think you ever quite "got it".
Type inference is not a gateway drug to more dynamically typed languages.
Rather "var" is a gateway drug toward "real" type inferencing, of which var is but a tiny cigarette to the greater crack mountain!
Type inference is used very effectively to create really expressive languages like ML, CAML, and the awesome F#.
These are ultra-static typed languages -- much more static than C#, as the compiler applies much more reasoning about types.
One of the inspirations for ML was a famous paper called "The next 500 languages" which called for the creation of a language called ISWIM, or "If you see what I mean". This proposed a lot of very aggressive type inferencing behaviour in the compiler, and it was embraced by the academic community.
"var" is but a tiny bagettal, a tip of the hat to that world. And hence i see it as a gateway to F#. The Language Of Teh Gods TM !!1!
cheers!
lb
really aggressively and powerfully in languages that are even more static than C#
as others said:
>You might even say implicit variable typing is a gateway drug to >Hindley-Milner type inference in statically typed languages. ;)
@masklinn is a dick
> 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.
Hey, thanks for proving once again the point I was making in my pair of abrasive posts (out of half a dozen): he was talking about OCaml's *type system* catching NPE (or more precisely making them impossible as the concept of null doesn't exist in the way it exists in Java).
Thanks for playing dude.
> you set yourself on a pedestal as coder supreme and treat everyone else as "uneducated retarded inbred morons".
I'm sorry I hurt your feelings and made you aware of your lack of knowledge in CS and computing (which you demonstrated again in this post), but you know... truth hurts sometimes.
@Dani Berg
> It just made me wonder how you compared PHP as a mess of functions and how organized is C#.
Simple. Implicit/explicit typing and static/dynamic typing are *completely orthogonal*.
So his point stands in that:
* C#, even with 3.0's type inference, stays *a statically typed language*, which Jeff seems to prefer. PHP is not and has never been statically typed (not that there's anything wrong with that)
* The design of PHP's STD as well as the design of the language itself still blows, that part of PHP hasn't changed.
@TraumaPony
> To a person, however, the latter is much clearer.
Not really. It may seem that way when that's all you've ever known though. I guess it's a case of blub
@Friedrich
> And well, even with some Oldtimer like Smalltalk one can write
>
>foo := Foo new
>.....
>
> I'm sorry but the whole explictly needed static type declaration stuff is so 80ies ;-)
Erm... I may have misunderstood your post but Smalltalk isn't statically typed at all.
masklinn on June 21, 2008 3:29 AMIf you don't like to type much, you should ditch C# and turn to D programming language.
auto R = new Reader();
And I'd say the "auto" keyword is a mere fraction of D's elegance, power and coolness.
Tomek on June 21, 2008 3:52 AMOk, after reading everyone's comments here, I guess I will revisit my code and make sure that when I do use var, it is only in places where it is unambiguous.
This is one of the reasons I read your blog, Jeff, the never ending quest to become a better coder.
Thanks Jeff and everyone!
Dennis on June 21, 2008 5:36 AMyou learn something new every day. I totally agree with you I always wondered why you need to specify the type essentially twice. Didn't know this was an option until now. What framework version though as I tend to like to stick with 2 unless I need a feature from a new version.
pete on June 21, 2008 6:28 AMJeff Atwood wrote:
"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?"
Sounds like a good idea, but I think it might be quite complicated to do in practice. Here's an example:
var x = 255; // It's a byte?
var y = sizeof(x) // 1?
x += 381; // Now it's a two-byte (unsigned) integer, or maybe a four-byte or eight-byte (depending on platform/cpu)?
y = sizeof(x); // 2?
In languages where primary types are not implemented as objects, I can imagine this kind of dynamic behaviour to be rather painful for the compiler/interpreter/virtual machine to keep track of. Also, it would break any assumptions about variable sizes in memory. For low-level stuff you may actually care.
I'm all for reducing redundancy and unwarranted verbosity, but increased ambiguity and complexity may be a high price to pay.
Anders Sandvig on June 21, 2008 7:19 AMMore often than not I agree with you Jeff.
I guess when it comes to readability, a more Verbose code is far better more concise code. With readability comes maintainability. Most of the time of developer is spent maintaining the code. While debugging I would like to have Verbose code. But then this is just my personal preference.
I <3 Perl
Steve on June 21, 2008 8:30 AMagree. even resharper has the same opinion
http://resharper.blogspot.com/2008/03/varification-using-implicitly-typed.html
agree. even resharper has the same opinion
http://resharper.blogspot.com/2008/03/varification-using-implicitly-typed.html
TraumaPony:
| "var pi = 3.14159: float or double?"
| If you know anything about C#, you'll know it's a double ;)
If the difference between getting a double var and a float var is a single trailing "F" way off on the right, isn't it clearer to type out "double"? Your intent was to have a double var (was it?); so why not let the maintainer(s) know that?
And I hate to drive this into the ground, but:
var pi = ThirdPartyLibraryForcedOnYou.ValueOfPI();
float or double? (Or String, or ComplexNumber, or AddressBookEntry?)
var warpedPI = 3.14159F * 2 / (2.01F * 1.0 + 2);
float or double?
Remember, I didn't write these, somebody else did... last year. What was the intent? Did she forget to make the 1.0 a float, or was it intentional? Did the guy who wrote "var pi = 3.14159" *intend* to make pi a double? It could matter. Where does he live so I may threaten him?
var value2 = Lib.MethodCall(45);
while (Console.ReadChar()!="") { value2 *= 2; }
Is value2 an int, long, float or double? Hell, is it a number? When will value2 overflow? If I modify a 1.0F to a 1.0 in an assignment, will I end up a truncation warning 30 lines down because my float var is now a double var and it's being crammed into a float parameter?
Yeah, the IDE can tell me or the compiler will whine or I can riddle through an expression or look on the right-hand side for an "F", but reading and maintaining it is much slower because of it. If the intent is "double", typing out "double" passes that intent along.
Craptaculus on June 21, 2008 12:20 PMJeff is trying to reinvent himself as a hardcore C# programamer meanwhile hoping to avoid having to explain his once proud VB roots.
Hoping this is just going to fade into the past I suspect like most C# converts from VB. Jeff, you've got too many pro-VB statements recorded for eternity in this blog for that to happen. You should just buck up and answer everyone who's asked, why you're not just using VB.
Pfff....
I agree, this was a lame post.
VBMan on June 21, 2008 1:37 PMI have to disagree with you here, Jeff.
Say I have a class named Example that implements two interfaces, IFoo and IBar. When I instantiate I have several options when dong so statically.
Example example1 = new Example();
IFoo example2 = new Example();
IBar example3 = new Example();
In the second case I am ensuring that example2 implements a certain interface, and I can swap this out with an instantiation of a different object that implements IFoo. This strategy pattern is fundamental to object oriented programming, and 'getting in the habit of writing code using var' can provide inflexible suboptimal design.
Interested in your thoughts.
var wordCounts = new Dictionary<string, int>();
-- YES PLEASE
Dictionary<string, int> wordcounts = new();
-- EVEN BETTER
var username = "Filbert";
-- NO THANKS (unnecessarily vague)
var mysteryObject = TheFactory.Create();
-- NO THANKS (requires too much work to find out the type)
This only works for local variables. Since you keep your methods nice and short (don't you?) I think there's really not a lot of scope for confusion. And there *is* value in stripping out redundancy if it can make your methods more concise and readable. I do, however, prefer not to use it such that the type becomes a complete mystery until you look up factory methods.
Weeble on June 21, 2008 5:10 PM@Mike G, et. al. with similar commments...
> 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.
Exactly what I was thinking!
From one VB convert to another, this really sounds like the VB programmer coming out in you Jeff :)
Fairly strong case of why var may not be the best tool is in your (Jeff's) "Sanitize HTML" post on RefactorMyCode:
http://www.refactormycode.com/codes/333-sanitize-html
The first several comments had valid points in stating they did not implicitly understand what your variable types were for your var's. Sure, RefactorMyCode is not a code review; but, during the refactoring process shouldn't you take into account the code-readability for future maintainers of your code (which brings us right back to your post 2 days ago)?
Kindler Chase on June 21, 2008 5:13 PMCraptaculus:
If you had read my previous post (it was RIGHT above it), then you would know that I agree with you. I was just pointing out that that exact example wasn't exactly a stellar one. A valid one, but a minor one.
If this is the coding style you like, you might enjoy learning ActionScript. Well, AS 2.0 at least. It supports but does not require strict data typing.
Jeremy White on June 21, 2008 8:57 PM"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'd suggest that your difficulties with C# syntax come from learning Python-like languages first, rather than any actual issue with C#'s syntax. I started with C++, and absolutely never have to stop and think about the syntax.
Whenever I have to write some VB though, I'm looking up syntax with almost every line of code.
Telos on June 21, 2008 11:25 PMWhat about the VB.net code, does this work on it too?
Omar Abid on June 22, 2008 1:22 AMim a bit of a n00b to coding, but I think the reason in C# is because:
BufferedReader br = new BufferedReader (new FileReader(name));
Creates an object on the heap.
BufferedReader br;
Would create a refrence to the class, allowing access to it's methods. Much shorter than System.IO.BufferedReader.whatevermethodyouwwanttouse();
> var mysteryObject = TheFactory.Create();
> -- NO THANKS (requires too much work to find out the type)
Much work? Just move the mouse over the "Create", and you're done. Or are you a dinosaur which prints source to view it? Last time i seen such a dinosaur was a hundred internet years back...
And give the Creator of that a routine a kick in the a***, and refactor the name of "Create", rename it to "CreateMedia", because it is creating a "Media"-Object. Or name it MediaFactory.Create(). Or .MediaCreate() - just follow your company guidelines.
Another point: If the Name of the class "Media" changes to "MediaDocument" because of refactoring, you only have to recompile the apps using this lib - nothing else to do! A mantaining nightmare if you have not used var. But you should refactor your apps steadily, so such changes are likely to happen.
titrat on June 22, 2008 1:53 AM@Jeremy White
> If this is the coding style you like, you might enjoy learning ActionScript. Well, AS 2.0 at least. It supports but does not require strict data typing.
Wrong. AS2 requires type annotation for static-ish typing and `var` without type annotation creates a *variant*, or if you prefer it creates an untyped object.
*C# DOESN'T DO THAT!*
In C#, `var` simply means "hey stupid compiler, get off your lazy ass and go check what the type of that thing is yourself. It does *not* make the language *any less* statically typed.
masklinn on June 22, 2008 2:23 AMWow...I normally get fustrated at the comments but rarely are they this...well. Anyway, to address some of the more reasonable comments and misunderstandings by pitching in my 2 cents and adding to the mayhem.
The key thing to point out is that it is of course optional. If you need to assign to a variable of a parent type or interface you can of course do this explicitly still (the important thing to remember is that there are two operations going on in a C style variable initialisation usually, variable declaration of "int i;" and variable assignment of "i = 10;" to become "int i = 10;").
The question I see arising from this though is whether the mix of styles is benificial or a hinderence. Is something like the following difficult to read?
var i = 5;
BaseClass b = new DerivedClass();
short s = 10;
var d = new DateTime(2008, 6, 22);
* Yes, single letter variables are bad. This is just for demonstrative purposes.
If you're in the situation where you're inevitably going to need to start mixing the styles, is it better to just stick with one?
int i = 5;
BaseClass b = new DerrivedClass();
short s = 10;
DateTime d = new DateTime(2008, 6, 22);
Personally when I started with C# 3.0 I decided to stick to the paradoxical mantra of "Implicit typing is for explicit situations". That is to say you should only use implicit typing (in C# where you inevitably have to use a mix of styles. This does not necessarily apply to more advanced type systems like Hindley-Milner) when the type that the compiler will infer is explicit.
Also, by the nature of it's implimentation it's use is largely restricted to local variables. So the times you will use a var is when it's explicit and local. This comes up quite a bit, but personaly I'm more comfortable with typing out the type explicitly - I've tried to force myself to use var but I've just never felt comfortable using it in a lot of situations. That's not to say it's bad though, I'm just the sort of person who enjoys some of the crufts of C for some peverse reason.
As for readibility and maintainability, in my limited experience I've never found it to be too much of a problem. Then again, I seem to be one of a rare breed of programmers who, if they're in a situation where the exact type of a variable is needed to be known either the code is poorly written and the variable names need to be refactored or there is a more subtle bug and I need to read the whole section of code carefully, variable declarations and all, so not being able to scan it in a microsecond isn't too much of a problem. (Note that point can be used for either side of the argument but leans ever to slightly towards implicit typing).
I guess my conclusion would be that personally I prefer to write code without var, but I have no objection to reading it as long as it's used sanely. I should add the disclaimer that I've never had to write or maintain a large body of code either with or without implicit typing, so my opinions are somewhat moot.
[ICR] on June 22, 2008 3:51 AMIt suprises me the number of people who seem adverse to using type suffixes (I don't know off the top of my head what they're actually called).
var pi = 3.14159 is a double. var pi = 3.14159f on the other hand will be a float. var maxentries = 5 will be an int. var maxentries = 5l will be a long.
float pi = 3.14159 won't even compile, you need float pi = 3.14159f, so the var variation doesn't lose very much information.
[ICR] on June 22, 2008 4:00 AMWell Mr Masklinn, I really enjoyed your posts! And their replies!
Yup, people don't like to be told that that they are lazy or shown that they are not competent at the job they do for a living as they like to think.
I certainly don't, but if I can learn something new, understand some concept more thoroughly and use it more efficiently and elegantly and thus become more competent then suffering a bit of professional embarrassment is worth it.
But if you spoke to me like that in person I'd thump you!
using var is no good style. Using var would never get through a code review at out company with good reasons. One interesting thing is that if you begin to type
Str outocpmpletion gives you StringBuilder
StringBuilder temp = new
gives you
StringBuilder temp = new StringBuilder();
So you make your typing unnessary complex without good structure.
gooofer on June 22, 2008 4:14 AMWow, jeff you have opened a religious can o worms here.
2 Sides to this story
=========
It seems to me that there are two sides to this and probably most people choose the side of the fence that they are most used to(is that chicken or egg first i don't know).
I prefer using the Type declaration but I've always been used to languages that use this. It does tell me extra information but I can see there are valid points to the other side. I suspect if I was used to type inference then I would choose that side by default too.
Use Another Language?
===================
Amongst the other suggestions has been one to use another language. This seems a bit silly to me. It takes time to learn another language and mastering it can take a months and years. Why put yourself through this extra overhead without some really obvious gain?
I don't think I'd try a major new undertaking, as you are doing with stackoverflow.com, with a language I am not familiar with.
That is not to say I wouldn't try out new languages, Python sounds pretty neat I might try it someday soon, but on smaller projects.
Tim Yen on June 22, 2008 5:05 AMTim Yen - Jeff wouldn't need to learn another language if he just used VB.NET though. That's his native tongue. It would be like going home.
Sarah on June 22, 2008 6:24 AM>Weeble:
>> var mysteryObject = TheFactory.Create();
>> -- NO THANKS (requires too much work to find out the type)
Titrat:
>Much work? Just move the mouse over the "Create", and you're done.
>Or are you a dinosaur which prints source to view it? Last time i
>seen such a dinosaur was a hundred internet years back...
I do think little things like this can still make a difference. It's one less little action to fit onto your mental stack while understanding a piece of code. Still, I could probably be convinced that it's okay so long as (as you suggest) the methods and classes are all very well named, and the method is nice and short so that the scope of the variable isn't too large.
[Titrat tells me off for poor names in my example]
Yeah, okay. It's not easy to quickly come up with realistic examples demonstrating great style while succinctly illustrating a point. :P
I'm interested in the idea that use of var makes refactoring easier (presumably across solutions). Does anyone have experience of this? Does it often make the difference between an awkward refactoring and an effortless one?
Weeble on June 22, 2008 8:03 AMWhat about in C#, how you can append a question mark to a type, such as:
int? myInt = MyFunction();
myInt will be an object with the HasValue and Value properties.
I discovered that last week. I wish i'd known that instead of using -1 as null for int. :P
Bobby on June 22, 2008 8:44 AMSo, you don't like calling constructors in a class, eh? You'll need to go back to the beginning of OO time to see the foundations of this nomenclature. The type and the constructor of the type generally have the same name. I think back to origins of Smalltalk and C++ as to why it evolved this way. Personally, I think it's a big time saver. But what do I know. I've only been doing this for twenty some odd years.
Blame the C# originators for looking at C++ and java for some sort of guidance? I don't know. But it seems silly to me. Want to do it a different way, adopt a different language.
Just so we understand apples and C#, most other languages don't let you initialize member variables in a class in the declaration section of the class. I think that's what the constructor is for?
Old Coder on June 22, 2008 9:01 AMi am still pretty new to java, but when i started i wondered alot about why i had to type the object name twice.
Andreas Vinter-Hviid on June 22, 2008 11:34 AMI agree in some respects but this does make it difficult when you are trying to teach new developers good OO design and tell them to always program to an interface. Code such as your examples would make it tougher on the compiler in that it would be forced to implement good design patterns for you. Take the following code for example:
InputStream stream = new BufferedInputStream(new FileInputStream(new File("file.txt")));
In the end I think it makes developers a tad bit lazier, and could make modern languages just as hard to follow as some of the scripting languages (just a possibility, and greatly depends upon the developer).
Matt Presson on June 22, 2008 3:54 PMI maintain roughly half a million lines of code for a living.
Redudancy is useful. Saying the same thing multiple times in slightly different ways is not important for a compiler, but when a human being is reading your code, having everything very clearly laid out really helps when someone comes along two years later and needs to understand it.
It consumes a few seconds when you write the code the first time, but it saves a few seconds when you come back to it. If you're writing something non-trivial, there's a good chance that people will be coming back to it for a long time to come.
I like bondage and discipline languages, because they allow me to build applications that are bigger and more powerful than thnigs thrown together in the scripting languages that are loved by enthusiasts who've never worked a 40-hour weekend on someone else's code that Has To Be Working On Monday.
Steve McConnell said "Good programmers know there's more to development than coding. Great programmers know there's more to development than development." He goes on to explain the importance of maintenance.
I think this comment is a sufficient illustration of my point that when communicating with a human (the guy who maintains your code), redundancy helps to clarify what you're trying to acheive, even if it does get annoying at times ;)
Nick Argall on June 22, 2008 5:02 PM"Did we learn nothing from VB and it's Variants?"
Variants sucked for different reasons. var is more like having option explicit turned off in vb6 (but not quite, since the compiler still knows whether you were trying to allocate a new variable or just mistyped something, which it couldn't do with option explicit turned off in vb6)
David Fauber on June 22, 2008 6:09 PM@Tim Yen
"Amongst the other suggestions has been one to use another language. This seems a bit silly to me. It takes time to learn another language and mastering it can take a months and years."
It's not silly, and languages like Python (yes, I am obviously biased towards it) are really easy to learn. Personally, the learning curve wasn't that "curved". Besides, it's not like you're learning a programming from scratch.
astigmatik on June 22, 2008 7:36 PMIn the case described I have to disagree. Right away I can think of two reasons to disagree:
-Inheritance: It would be unclear exactly what type the variable would be and exactly how it would respond to re-initialization to one of the many child types of a base type.
-Just like in VB where that same variable can be re-initialized to whatever breaks consistency of the variable...it can go from int to string, then to whatever else. In C++ if I make it an int it will be an int for its whole existence...until it goes out of scope. That syntax just makes it impossible to tell what type a variable unless you track down all the operations/commands done to it since its creation. I would not have any of this....ever!
Of course you could set yourself some rules about not re-initializing a variable or changing its type, but then again whats to say everyone else will respect this rule.
Then of course when it happens....I would hate to be there to have to track this down and fix it.
Dominic Montreuil on June 22, 2008 9:22 PM@Matt Presson
> this does make it difficult when you are trying to teach new developers good OO design and tell them to always program to an interface
No it doesn't, but it does force you to think about what that means, which you clearly seem not to have done.
Coding to interface is a good principle at the boundaries of functions at APIs. Within a function (which, once again, is the best `var` can do as it's *local* type inference) it does *not* matter.
> Code such as your examples would make it tougher on the compiler in that it would be forced to implement good design patterns for you.
Oh noes, you mean compiler writers for C# or Java would have to learn about compiler techniques that are 20+ years old, widely studied and with stacks of books and practical and theoretical background?
The horror!
@Dominic Montreuil
> It would be unclear exactly what type the variable would be and exactly how it would respond to re-initialization to one of the many child types of a base type.
Not necessarily, depends on the quality and flexibility of the type inference system (as I already pointed out several times, there are type inference system which infer the most generic type possible, including abstract types)
> Just like in VB where that same variable can be re-initialized to whatever breaks consistency of the variable...it can go from int to string, then to whatever else.
And people wonder why I posted abusive comments...
You don't have a fucking clue about what var does, yet seem to have no problem talking shit about it. Var is nothing like a VB Variant type, please shut the fuck up, learn what static type inference does, and then go shoot yourself.
> That syntax just makes it impossible to tell what type a variable unless you track down all the operations/commands done to it since its creation.
fail.
masklinn on June 23, 2008 12:19 AMOK i think you are all going supersonic with this. Dynamic typing is OK but please keep it simple. In my opinion a programing language should have as few automagic constructs as possible. If I expect an integer I do not get why I should check if the funny blob of data that wandered into my function is an integer or drop down list.
I do get the advantages of dynamic typing but they just cant convince me go and do what was done in the blog entry. The StringBuilder is still a StringBuilder through its whole life time.
One little quote: "If you change the the name of a rose it will still smell the same".
thx
Dejan Fajfar on June 23, 2008 12:58 AMPersonally, I was more in favor of an "assignment operator"-like syntax, which would have been, at least, easier to parse for the compiler (but not necessarily for the user). However, it would also be usable somewhere else than in declarations, which may not be that good a thing :
StringBuilder sb new=(256);
BufferedReader br;
br new=(new FileReader(name));
int[] arr new=[] {1,2,3};
object obj = ...
SomeClass realObj;
realObj cast= obj;
The main advantage is that we are familiar with the fact assignment operators use the type of the left argument. A major drawback is that for the untrained eye, it becomes very difficult to read without syntax highlighting.
Medinoc on June 23, 2008 1:17 AMI'm an ActionScript programmer - we've only in the last couple of years had static typing - and I have to say what you're doing seems like a big step backwards. What have you gained by not explicitly typing your variable? It saves you about 5 seconds while you code. But what you've lost is clarity for whoever has to look at your code next.
Iain on June 23, 2008 4:56 AMBufferedReader br = new BufferedReader (new FileReader(name));
is quite as cruel as
var br = new BufferedReader (new FileReader(name));
why not something like
<new> type varName <(parameters)>;
new BufferedReader br (new FileReader(name));
used less/greater instead of square brackets, so the fifth line looked silly, should read:
[new] type varName [(parameters)];
Don't like pi = 3.14159;
is it a double, a float or a decimal?
@Dejan Fajfar
> I do get the advantages of dynamic typing but they just cant convince me go and do what was done in the blog entry.
Oh, hey, look at that, another idiot...
Here's for you Mr Stupid: var is not dynamic typing in any way, shape or form. Gb2GradeSchool.
@stEvil
> Don't like pi = 3.14159;
> is it a double, a float or a decimal?
It's a double, because that's what C# creates by default
masklinn on June 23, 2008 5:58 AMIf you feel that explicit typing when creating a new object is redundant, then I would argue that by using var you are attempting to solve the wrong side of the redundancy.
It just so happens that to invoke a constructor you must specify the name of the class. If C# were to one day remove this syntax, you could re-write your examples as follows:
StringBuilder sb = new(256);
UTF8Encoding e = new();
MD5CryptoServiceProvider md5 = new();
This is a much better way of reducing the amount of code, in my opinion, while retaining the clear, static typing that you get when you do not use the new keyword, such as:
StringBuilder sb = MyObject.CreateBuilder();
If you were to use your method in the above example, you wouldn't have a clue what type my "CreateBuilder()" was returning unless you hovered your mouse over the method definition, which of course makes readability suffer.
Cheers,
Roger
"Don't like pi = 3.14159;
is it a double, a float or a decimal?"
Just like in the pre-var days, you would have to specify the datatype on the right side of the equation if you are assigning to anything other than a double. Nothing new here.
Are you under the impression that the compiler wouldn't complain if you wrote something like
float pi = 3.14159
I have to say I disagree with you on this one Jeff.
This is a very bad practice in my opinion. The more explicit we can be in what we mean in the code, the better. There is a big different between.
StringBuilder sb = new StringBuilder(256);
and
IBuildable builder = new StringBuilder(256);
Perhaps thats not the best example, but I think you get the point. When we throw var in there, it makes it so we have to actually look at the assignment to figure out the variable type.
The main reason var was introduced was to be able to hold anonymous classes. I am not saying there aren't other uses for it, but it should definitely be used sparingly.
Sure, sometimes its easy to infer the type just by looking at the first assignment, but sometimes it is not. When using a factory, the factory may return an interface. Methods that return IEnumarable<blah> are not very obvious when used with a var.
Finally, when you declare the type of you variable instead of using blah, you have to actually make a concious decision to use the concrete type instead of the interface (where appropriate.) Using var all over the place definitely make it much more likely that a programmer will not code to interface. I guess I would liken it to not initialiing the default value of variables. There are some places where this is an ok practice, and saves redundancy, but in general it is a good idea to initialize variables.
Programmers don't come pre-equipped with the same type inference logic the compiler does, so as I see it all the name-calling and technical discussion boils down to two issues:
1. Does the feature make an individual developer more productive in writing code?
2. Does the feature make the code a developer produces more easily maintained by other human developers?
I think it's clear that the answer to #1 is yes, if only in the reduction of redundancy. I don't think it's a huge improvement in productivity, but it's there.
I also think it's clear that the answer to #2 is no, as a human being has to work harder to extract out the real type (and the maintenance consequences of that real type) and has to manually apply the same logic the compiler does.
In my opinion, the negatives from #2 outweigh the benefits of #1 in most cases. "var" obscures the programmer's intent from other humans by relying on compiler mind-reading rather than an explicit spelling-out of intent. I can see areas where this feature would certainly be useful, but I wouldn't allow unrestrained use of it in my organization.
Matt Wigdahl on June 23, 2008 7:05 AMThis post started off reasonable enough, but just about jumped off a cliff afterwards.
I'm all in favour of "var sb = new StringBuilder()" to avoid the redundancy. But I sincerely hope that you don't think "var maxentries = 5" and "var pi = 3.14159" are good ideas. Aside from constants being declared as variables, you're not even saving a single keystroke over "int" (and is "double" really that hard?), and your suggestion of "autosizing" not only can't work in the latter case (fixed point to floating point = loss of precision), but isn't always going to be the desired behaviour (i.e. when interfacing with a database or static library).
Frankly, it irritates me when people try to suggest that C# should imitate Ruby or old-school BASIC. Yuck. Type inference is not the same as dynamic typing!
Aaron G on June 23, 2008 7:30 AMThis looks to be an exercise in reducing typing (in both senses!) at the expense of clarity
Isn't this what code-completion/intellisense is all about, yes it looks a lot to type but you never actually type it all in ...
If variable type can only be resolved at run time then you no longer have a statically typed language ...
If variable type can only be resolved by the compiler then you *will* have type errors sooner or later ...
Jaster on June 23, 2008 7:42 AMIn this thread, masklinn is the sane voice when it comes to the subject area. It is just to sad that he/she has to wrap it in such abrasive language.
Please people, try to remember that var is a) still statically typed, and b) function local.
Also, just because Visual Studio has a nice auto-complete feature doesn't mean that it is always available when writing code in a language. For example, Visual Studio is obviously not available on Linux, but C# is.
MZL on June 23, 2008 7:50 AMI actually disagree with your assessment. The "var" in C# was a necessary evil for a specific purpose, that leave a bad taste in my mouth, though, i understand and respect the addition into the C# 3.0 specification. It wasn't added to reduce redundancy, it was added, because, given the new linq integration, you can not always determine the variable types at design time. However, at run-time this does become strongly typed. This is a bit hard to describe in this forum, however, I gave a presentation on it at a .NET user group meeting once.
You are using the new "feature" functionally correct, but I think very badly for the purpose of design. I don't think it is redundant to explicitly declare a variables type. And the variable type of the right hand side of the assignment isn't always what you want the variable type of the assignee (left side).
SomeBase Obj = new SomeDerived("option");
// Either way, i think it's important for maintainable code to be
// explicit.
@Bart:
> 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));
But BufferedReader is a kind of ParentClassOfBufferedReader. So wherever you'd use ParentClassOfBufferedReader you could as well use BufferedReader and it makes no difference to your code or the generated code at all.
Typing br in a different manner only makes sense if you later on plan to do
br = new UltraCoolBufferedReader(...);
and UltraCoolBufferedReader is also a subclass of ParentClassOfBufferedReader, but otherwise unrelated to BufferedReader.
But then again, there are very little cases where this will be ever necessary. Variable re-using is bad practice. E.g. I dislike code like this
int counter;
// Count how often a certain pattern appears in a string
counter = FindMatchesInString(string, pattern);
// ...
// Count the number of files in the current directory
counter = Directory.numberOfFiles();
The same variable is used twice for completely different purposes. Instead you should have used numberOfPatternMatches and numberOfFilesInDirectory (make them short, I had used numOfMatches and numOfFiles, doesn't matter). The name of a variable should tell the reader what it is good for. What is counter good for? What does it count?
Reusing variables is something you will find in old-school code, where every variable was using space on stack or got a CPU register assigned. Modern compilers are much better at optimizing. E.g. if you use two ints, one in the upper part of the function and one in the lower one and either not even the scopes of both ever cross or they do cross, but the first one is never used in the second part and the other way round and there is no way to ever go back from the second part to the first one, a good compiler will in fact only reserve space for one int on stack (or assign one register for both), as it can re-use the space when the function leaves the first part and enters the second one.
So there are little reasons you ever need to explicitly type to a parent class. Even for function calls the result type is known:
var x = getMeSomeValue();
The compiler knows what type this function will return, so it can assign the correct type to x. There are some rare cases, however, where you run over a set of items of different types and to keep the loop simple, you always want all references in one variable, instead of one per type. Okay, but then you can still use casting instead of of typing. E.g.
Object o = ...
Could be written as
var o = (Object)...
By casting to Object, the compiler knows, that the type is object and not whatever ... provides. This way you can up- or downcast. Actually your example above is nothing more than an implicit upcast that languages allow for simplicity (so you can use a child exactly the same way as you could do with its parent in every place and every time) - make it an explicit cast and you'll be fine. Not that it would save you any typing work (the first one is shorter than the second one).
I personally prefer dynamic typing in development, since it often makes code so much easier and it is very powerful. The downside is that most checking happens at runtime vs checking at compile time. However if you can eliminate most runtime checking, dynamic typing is a very powerful tool if you don't misuse it as some languages allow you. E.g. the following PHP code is horrible IMHO:
$i = 10;
// ...
$i = "Blah"
Use dynamic typing, but stay with the type wherever possible.
Mecki on June 23, 2008 8:17 AMThis used to bother me a lot when I first started coding.
Right now I'm kind of neutral. My feeling is that most of the time, this:
BufferedReader br = new BufferedReader (new FileReader(name));
is simply incorrect code. It should almost always be:
Reader r = new BufferedReader (new FileReader(name));
Being as general as possible while still being able to do your functions is fairly important. If you were to refactor a piece of this code into a method, catching that incorrect code above could be the difference between making your method signature too specific or not.
In fact, I've heard it argued (by better programmers than myself) that you should never have anything to the right of an object that is not an interface. Since it's impossible to instantiate an interface, you could say that:
<obj> var = new <obj>
Is a completely illegal pattern and should never happen.
That said, in my experience few people really program in such a way that this differentiation gets above the noise level, so I'm not arguing the point, just pointing out the concept.
This used to bother me a lot when I first started coding.
Right now I'm kind of neutral. My feeling is that most of the time, this:
BufferedReader br = new BufferedReader (new FileReader(name));
is simply incorrect code. It should almost always be:
Reader r = new BufferedReader (new FileReader(name));
Being as general as possible while still being able to do your functions is fairly important. If you were to refactor a piece of this code into a method, catching that incorrect code above could be the difference between making your method signature too specific or not.
In fact, I've heard it argued (by better programmers than myself) that you should never have anything to the right of an object that is not an interface. Since it's impossible to instantiate an interface, you could say that:
var = new
Is a completely illegal pattern and should never happen.
That said, in my experience few people really program in such a way that this differentiation gets above the noise level, so I'm not arguing the point, just pointing out the concept.
I'm just glad I don't need to maintain your code.
Jo on June 23, 2008 8:29 AMYou need this "redundancy" when leveraging the OO concept of inheritnace. Take Java collections for instance.
Collection objects = new HashSet();
If I don't want to expose all the HashSet functionality, I shouldn't have too. Consider that versus
var objects = new HashSet(); //What if I want objects to only expose the Collections interface?
And if we allow both conventions, then our code gets completely convoluded and loses readability.
Collection objects = new HashSet();
var hashObjects = new HashSet();
Or we can use casting, which I don't like.
var objects =(Collection) new HashSet();
var hashObjects = new HashSet();
I think it's fine the way it is. That's what code completion is for after all right?
@masklinn
wow, you really are a right flaming ass aren't you. You apparently operate under the assumption that because this is the internet you have no need for basic courtesy. Does it make you happy being such a raging dick to people? Does your life feel more fulfilled because you have a place where you can be as caustic as you wish without fear of being punched in the face like you would in meatspace?
To return the favor, you obviously don't know anything about real development at dev houses of any decent size, and come across as an amateur developer with detailed technical knowledge but no experience in collaborative development environments. Good code has absolutely nothing to do with how effective it is at doing a job but rather how clearly it does the job when interpretted by other team members. Local scope vars have plenty of uses (though in reality they weren't added to the runtime to benefit C# at all but where instead to support dynamic languages. The benefits they bring to C# are entirely tangential) but the lack of explicit typing does reduce explicit understanding among a team made up of people of a variety of experience, AS THIS THREAD CLEARLY DEMONSTRATES. It doesn't matter how something works, how slick it gets the job done, when other people consuming the code don't understand.
I can think of a lot of reasons why var usage is applicable, situations where it makes sense to use, but to reduce the amount of typing someone needs to do when actually declaring the variable is one of the poorest justifications I can think for its use. The actual act of typing code is by far the least time consuming process in creating code, and the fraction of time saved by typing var rather than ArrayList is utterly trivial. It amounts to saying "I am using this to be lazy" which is poor justification for any code decision. It is no different in justification than people using aliased "using" to shorten a class name (using al = System.Collections.ArrayList). var should be used when the code benefits from implicit type local variables, essentially when working with anonymous data types cleanly to avoid multiple explicit type queries and castings.
Joshbw on June 23, 2008 9:05 AMI was going to mention Scala, but I see that's too advanced for most people remarking here.
So, two other comments.
First, if the IDE can auto-complete with CTRL-space, why the hell can't it just SHOW you the type, without it actually having to be there?
var <type inserted by IDE without actually being present> x = whatever;
It handles everything. Factory, methods, etc.
Second comment, about var x = 1. The type of x should be NUMBER. Int, shortint, long, float, double, etc are artifacts of an age were people where concerned about exactly how many bytes were needed for storage allocation, and had to optimize performance by hand. We are past that. The type of x should be number, and is the job of the COMPILER to properly optimize for size and speed as needed.
Alas, I'll correct myself. It is the job of the VIRTUAL MACHINE to optimize it for size and speed as actually demanded by the running instance of the program.
God, I never thought we'd actually consider garbage collection a given before we took short to the back and shot it in the head.
-- It handles everything. Factory, methods, etc.
Hmmm...
public Class Car : IDrivable, IAutomobile, ISteer, ISerializable
{
...
}
// Create a car referencing by the concrete type
A
Car myCar = new Car();
B
var myCar = new Car();
// Create a car using the factory method
A
Car myCar = Car.Create();
B
var myCar = Car.Create(); // Whoops, did it return an interface or a concrete class, I'm not sure. Have to hover over to find out.
// Create a car reference by IDrivable interface
A
IDrivable myCar = new Car();
B
// DOH
// We can cheat with:
var myCar = (IDrivable)new Car();
// etc ...
John on June 23, 2008 11:31 AMJohn, does the language use static typing? If it does, then Car.Create() can return only one thing. That thing is calculated by the compiler, and, in fact, checked against the type you assigned. If it didn't check it, the static typing would have no value whatsoever. So it is a given that Car.Create() has a _static_ type, which the compiler _does_ infer at _compile_ time.
If the compiler can do so, so can the IDE. So, did it return an interface of concrete class? Well, the IDE does know so, and it can _display_ that information to you. Where the code is
var myCar = Car.Create();
it would _show_
var Car myCar = Car.Create();
And, obviously, display that "Car" in a way that it leaves no doubt it isn't actually in the code, just like syntax highlights aren't actually in the code. Personally, I'd draw a little box around it, with an inside background a little shaded, like used in some books.
But, anyway, the point is that if the IDE can auto-complete, it can also display without inserting it. If the compiler can type check, so can the IDE. You could have this anywhere, in fact. It could display a variable's type at all assignments to it, it could display a method's parameters type at all calls, etc. And, of course, show and hide at will.
I'm not asserting you don't need to type what the compiler doesn't know. That's another issue. But people here are complaining that having the type there (duplicated, most of the time) helps understanding the code. Well, ok. But as long as the SOLE purpose is helping people understand the code, the IDE can do that.
Daniel on June 23, 2008 12:15 PM@Bill
"This used to bother me a lot when I first started coding.
Right now I'm kind of neutral. My feeling is that most of the time, this:
BufferedReader br = new BufferedReader (new FileReader(name));
is simply incorrect code. It should almost always be:
Reader r = new BufferedReader (new FileReader(name));
"
This makes no sense. Most of the time I use a BufferedReader, it's because I need the "readLine()" method, which is not declared in Reader. Since BufferedReader br = new BufferedReader(...) is considered bad practice, how are you supposd to be able to access "readLine()"?
@Daniel
Car.Create only returns one thing, true.
But, you can use it as any number of interfaces that are implemented by the type.
In addition you don't know if Car.Create is returning only a specific interface, or the actual full class, till you look at its signature, if written with a var.
Half of the people posting here don't even understand what interfaces are, or what they are used for. I think this is the largest part of the confusion. If you don't know why, Bill's post about
"It should almost always be:
Reader r = new BufferedReader(new FileReader(name));
"
then you have much much larger issues in your knowledge of good designa and to be honest, aren't even worthy to comment on the use of var or not.
John on June 23, 2008 1:24 PMHaving spent a considerable part of my career on maintenance programming, I'm firmly against var. Making the maintainer waste time to figure out variable typing for your own convenience is just lazy and rude. Intellisense is not always available on projects where code rot has set in.
I agree with an earlier poster: var should be treated the same as goto, a tool to be used very sparingly and only to solve the problems for which it is intended. Frivolous use should be flagged for removal at code reviews.
BH on June 23, 2008 1:47 PM@KG don't fear - in that instance you're well within your rights to use the object.
I guess Bill should have wrote that _most_ of the time it's probably incorrect, with the idea being that the reference you hold on to should be the most generic (highest up the base class) than you can afford to go. If using Reader isn't going to cut it, then don't use it.
The idea is more powerful and apparent when a method accepts a type B, where B is derived from A, and the method in question only uses methods as defined in A. You can refactor the method to accept A's instead.
I'm not sure I agree that one always have to do the replacement in a declaration scenario that Bill writes about. The only time I find it necessary is with interfaces and/or factory methods. When you don't know, and don't care about the specific object. This is where it's more powerful.
I'll pipe in that var sucks as well. Only should be used for linq / anon classes.
Legacy on June 23, 2008 1:53 PMMaybe we'll get used to seeing var'd code. In as much as it takes time for one's brain to skip the (sometimes) redundant declaration+assign, we'll probably get used to it, but we need to come up with clear rules, because the overuse of var will kill it's usefulness and lead it being led to the halls of shame next to goto. Goto's are perfectly valid and useful, but were overused and banned because they made the code too hard to follow.
---
Code is meant to be read by humans so it doesn't matter what fancy tricks your compiler gives you, if it makes the code harder to maintain (too terse, etc) then it's not worth the time upfront you save by writing out a few extra characters.
We split code into files and projects, base classes and inheritance, interfaces, etc to make coding easier for the coders. The compiler has never had a problem compiling code, and would still be happy if we were all writing assembler.
---
I tried it with Java once, and produced a valid Java haiku:
ArrayList<int> myListOfInt = new ArrayList<int>();
which, spoken aloud, reads:
ArrayList of Int
my list of int, equals new
ArrayList of Int
Maybe it's just me, but I find it pretty farging depressing that a simple declaration like that can be haiku-sized in Java.
--
http://steve-yegge.blogspot.com/2006/10/egomania-itself.html
Pretty farging depressing, indeed.
Okay, I'm just going to throw this out. How about allowing the followging syntax in Java or C#:
StringBuilder sb(256);
// Above the same as StringBuilder sb = new StringBuilder(256);
It seems like those who do not like "var" do not like the fact that the type does not come first, which makes it hard to read. So, why not put it first. Granted, it looks like a C++ automatic variable declaration, but it's much less verbose and does make the type more explicit.
Comments welcome.
Carleton on June 23, 2008 6:18 PMC++0x will have a feature like this. Useful to shorten foreach-like loops:
vector<vector<int> > v;
for (vector<vector<int> >::iterator i = v.begin(); i != v.end(); ++i)
into
for (auto i = v.begin(); i != v.end(); ++i)
But actually, C++0x will have a real foreach anyway.
for(vector<int> &x : v)
Nicolas on June 23, 2008 7:31 PMI hate you and your stupid angle-bracket-eating blog comment system.
Nicolas on June 23, 2008 8:31 PM@Jeff:
Pretty poor example. I sincerely doubt Perl haiku writers use variable names like "myListOfInt". Probably more like "a". In any case comparing Java to Perl is hardly an argument for using _var_.
Really, this whole thing sounds like a bad case of C# jumping up and down whining "Me too, me too!" when around Ruby/Perl. I think developers _choosing_ to use C# instead of Visual Basic should stand by their choice. I have little doubt that C# v4 will officially be the bastard child of Python and Visual Basic.
Anyway, there's been enough backlash on this topic that I hope you address it again. I'd really like to see more rationale and analysis of how the direction C# is going (and these other "new age" languages fit into the principles of the Coding Horror Bible (CodeComplete). If you ask me the hip new mantra seems to be "verbose is bad, obscure shorthand is good!"
Nick on June 23, 2008 8:46 PM> I hate you and your stupid angle-bracket-eating blog comment system.
LOL
Sorry. This will be fixed stackoverflow. It is incredibly annoying I agree.
Jeff Atwood on June 23, 2008 9:56 PMSo much wrongness ...
- The IDE is not always there, and you don't always have code that makes the IDE happy and intelligent. And when the IDE is confused or not present at all, you still need to know the exact type of your variables to see where the bugs may lie.
- Exposing internal structures even within the function that created the object is still an obstruction to refactoring (more so when the so-called developer of the code you need to refactor does not mind having Godlike monster functions).
- Reassigning a variable is not a rare event, and is a stumbling block for smart type inference. Consider this:
class IFoo;
class CFoo1 : IFoo;
class CFoo2 : IFoo;
var obj = new CFoo1();
// do some testing, and let's use optimized CFoo1 methods instead of what IFoo gives us ...
try { obj.CFoo1SpecificFn()) }
catch ...
// oops, turns out that CFoo1 is not suitable for the task, let's use CFoo2 instead ...
obj = new CFoo2();
Now, what class will obj be? If type inference is local, I'll get CFoo1 and a barf at the last line, which is perfectly legitimate. If type inference is global, then obj will be locked to CFoo1 by the middle line anyway, so I will still get a barf at the last line instead of the middle one. Getting errors not where they really belong does not make a code monkey happy.
Apart from those issues, of course any optional feature is good! Up to the time you have to read and understand and fix code written by people who didn't exercise restraint when using this feature.
One of the points the MS seemed to be driving home when they introduced anonymous types (which some people seem to have confused with dynamic types) was that they intended their Intellisense tool to be relied on to determine which methods and properties are available on the 'var'.
My immediate response was this: If Intellisense is smart enough to infer everything we need to know about the type of an object, then it's beginning to sound like the static type checking in the compiler is the true redundancy here.
After all, the best place to catch errors is when you're writing them. I know that Intellisense is just another tool, but it's better than learning the interfaces to the thousands of classes in the .NET Base Class Library.
When I was a proponent of statically typed languages, no one could have convinced me that dynamic typing was better. After I drank the Cool-Aid of dynamically typed languages, I remember how I used to think, so I rarely try to convince people that dynamic typing is better.
My point is, based on the MS reasoning that Intellisense will always be there to tell you everything you need, why keep static typing around? Would anyone notice if you could leave off all type declarations tomorrow? Or would everyone still have their nose buried in Intellisense?
Loren on June 24, 2008 2:12 AMLike you say, there is a trade off here. With dynamically typed languages you don't really have to worry about this sort of thing at all, as it all gets handled at runtime. However, you run the risk of passing the wrong type and getting a runtime error. With strongly typed languages you do get a significant overhead ("redundancy") but any type errors will be caught at compile time.
I think you're right that a combination of both is probably best, and from the looks of this article C# is moving towards a more dynamic approach, and PHP is certainly moving towards more support for static typing with type hints.
Ben on June 24, 2008 2:31 AMUnfortunately I do not program enough in c# to judge, but have not had issues with having to repeat myself in Java.
I do see possible issues with using var though.
Animal x = new Cat();
// blah blah blah
x = new Dog();
I presume that when var was introduced, two things were kept in mind:
1) you can still use regular declaration;
2) it's the compiler that catches wrong assignments, rather than being evaluated during runtime.
My biggest issue is that, in a situation above, I would put down:
var x = new Cat();
and then later forgetting about automatic typing, I would try to assign Dog to x.
x = new Dog();
I will have to go back and fix it now, wouldn't I? But I would have to fix it anyway, as I would put Cat x = new Cat() anyway...
From what it seems like, it's not something that is forced upon people. However I see some people abusing it and that is probably what pisses a lot of people off that wrote pretty hateful comments :)
vshioshvili on June 24, 2008 7:22 AM@Tepsifles
> Now, what class will obj be? If type inference is local, I'll get CFoo1 and a barf at the last line, which is perfectly legitimate. If type inference is global, then obj will be locked to CFoo1 by the middle line anyway, so I will still get a barf at the last line instead of the middle one.
I sure hope so as in both case the program is ill-typed, the compiler would be pretty dismal if it didn't report an error.
@vshioshvili
You don't make any damn sense, but as far as your examples go, with a type-inference system either the compiler would raise an error because the "Cat" and "Dog" types are incompatible (if they are), or it would look for and use (if any) the lowest applicable common type.
Now if *that* results in a logic error, then you've got your type hierarchy wrong, and the blames rests on you not on the TI system.
masklinn on June 24, 2008 8:07 AM@masklinn
The program is not ill-typed. The attempt there is to use an interface reference instead of a concrete class reference. It makes perfect sense, and it won't work with vars.
Also vshioshvili makes perfect sense. Polymorphism.
Did somebody mention D. Is this language still around?
I remember people giving talks about this language and undergraduate students learn C and C++ found silly, leave alone the professors.
I love this blog. There is always something that I learn or something that tickles me.
Ivan on June 24, 2008 10:13 AMI don't understand how did Perl find its way into this conversation at all. Though a great language to do many things with (if you like unintelligible code and were born before Ruby or Python were invented), it is not a real OO language. Well, unless we are talking about Perl 6 which was a good 10 years late in appearing on the scene.
Anvar on June 24, 2008 10:31 AM@John: I understand precisely what is being said. The people saying it, though, don't seem to have a real good grasp on type theory, and keep sprouting nonsense.
So let me put it this way. Static typing has very specific benefits, which do not require the verbosity Java does. Compare Scala, with it's much superior typing system, to Java. Scala, providing much more benefits than Java, isn't as much verbose as Java.
So, the compile-time benefits of static typing do not require such verbosity. Humans, are another matter. But because the compiler _knows_ what the code is _actually_ doing, a smart IDE can inform the user without requiring repetitive typing by the programmer.
So let's deal with that case. I have a variable X to which I assign an object. Now, the IDE knows what type X actually have. It can show the user that type. Say you want to know what is the interface being implemented. The IDE can show that too, or instead.
Let's make it difficult. Assume the language allows multiple classes for each object (sic -- not multiple inheritance), and multiple interfaces for each class, or even multiple interfaces for an object not necessarily related to a single class. As it happens, I used such a language. The object could also change it's interfaces and class throughout it's life, but leave that alone and assume static typing.
So, you have X with an Object. The IDE can show you what classes and interfaces it supports and what is the minimum set of interfaces and classes it is being required of it.
So, not only the IDE can show that, in "var x = new BufferedReader(...)", x is a BufferedReader implementing the interface Reader, it could also show that, in fact, the code is requiring x to be of BufferedReader class, and not simply and object implementing Reader.
Whether that would be correct or not, of course, is a matter to be decided by humans.
@Tepsifules: that's not actually allowed on most static typing systems, unless you do casting. We are discussing a language with a static typing system. Not a very good one, but a static one.
How would you go about declaring it by interface or superclass? If you declare obj to be IFoo, then you have to typecast it to get IFoo1's method. If you declare it to be IFoo1, the later assignment is invalid.
@those who think requiring smart IDE's is a no-no. Well, requiring virtual machines and garbage collection was also a no-no for a long time, but it doesn't seem to bother many people anymore.
In fact, people complain when a language doesn't have automatic refactoring tools available.
Truly, people, I have go to vi, not vim, and lose syntax highlighting, and that will make it harder to debug the language. I won't know what methods are available, what's the class hierarchy, I won't be able to instantly retrieve the source to the class from whatever file and directory it is located, etc. Yes, without the proper tools, it will be tougher. So don't use that if you lack proper tools, but don't try to stop ADVANCED language features on the premise that the tools won't support it!
@Loren: it's not the compiler that is statically typed, it's the language. Yes, it is MUCH better to catch the errors while writing the code. In fact, I have seen setups which continuously run _unit tests_ while you write the code.
The point is that if the language is statically typed, any tool can catch specific errors that would not otherwise be possible.
As a historical reference, the C compiler was very, very lenient on code in the past. If you wanted to do a more strong check, you ran your code through LINT, which was not concerned with _compiling_ code, just checking it.
Daniel on June 24, 2008 11:54 AM.....One day all this will be ECMAscript....
Phil H on June 24, 2008 12:36 PM@Tepsifles
- when the IDE is confused or not present at all, you still need to know the exact type of your variables
Agreed. Who cares about the IDE.
- Exposing internal structures even within the function that created the object is still an obstruction to refactoring
Disagree. Once you name the type via "new" or factory return type, the dependency exists. var does not create additional dependency.
I'm open to seeing examples of refactoring that are blocked by use of var.
class IFoo;
class CFoo1 : IFoo;
class CFoo2 : IFoo;
//obj is clearly a CFoo1 reference.
var obj = new CFoo1();
// this works as long as CFoo1 has the CFoo1SpecificFn
obj.CFoo1SpecificFn()
// this is a compile time error. The code will not compile.
obj = new CFoo2();
- Apart from those issues, of course any optional feature is good! Up to the time you have to read and understand and fix code written by people who didn't exercise restraint when using this feature.
Those people are still writing 10 level deep nested if trees or using dynamic sql. They are already doomed.
I do not understand how allowing unclear code can possibly be a good thing?
Joey on June 24, 2008 2:28 PM1. var = inferred typing. var != dynamic typing
2. @Loren you don't always use an IDE to generate code. You don't have to use CodeDom either. A code generator can spit out plain old text files to be compiled by a make file. The compiler has the final say. Also, what per se is the Kool-Aid of dynamically typed languages. Why are they so much better? Links please.
3. Is there such a thing as dynamic typing, or is it just a fancy way to say 'variant' under-the-covers? If so, why did people complain so much about vbscript? Everything's a variant and I hated using it, and like every interpreted language, every method is evaluated at runtime. Javascript is cooler though because you can inject methods on the fly, but only because in javascript the base object is really a hashmap.
4. We create compiled programs because uncompiled (or interpreted) programs are:
a. slower, but jit'ing is common, so this is moot.
b. harder to track down typing bugs, because you only get notified of being stupid at runtime, not compile time
c. perhaps safer, because you can't just Eval() arbitrary text. But the C# has CodeDom and you can compile assemblies on the fly, so that's not really a factor either (but at least in the CLR you can restrict this ability)
---
So you pay the same tax _somewhere_. And considering typing errors are pretty freaking common, compiling is a nice first pass so I don't have to click through 5 pages just to get an error that Console.WretiLine(s) is an unknown method. Darn my dyslexic fingers.
OK, sure dynamic typing lets you do _some_ things that aren't as natural as an OO heavily typed language. But then the whole freaking benefit of C# and CLR based programs is the rich and *explicit* type system - the manifest exposing exactly what everything in the assembly looks like - no surprises. No more obscure references and monolithic binaries (C,C++) and header files that say we're pretty sure that we need to pass something that looks like .....
Everything's a tradeoff. I won't say Python is better than C#, and neither will I say C# is better than Python. I must be a moron because I like and use both, and both have their uses. I do object to overly terse languages, or languages that don't promote good coding practices.
Explicitness is a good thing because it resolves ambiguities. Writing unambiguous code is a boon for maintenance, which code becomes the second you've written it.
My wish is one day to see an apples to apples comparison of languages and their features that doesn't use idiotic trivial examples, nor promote one silly feature above all others (unless it really is that good). Sure your language of the day may have Xml processing built in, but does that make it trump all other known languages? I can't recall how many times a new language pops up and a few dedicated people scramble to make it add libraries to do everything all the other language used to do.
About the only thing I've read in this entire thread that might be a worthwhile addition to the C# language is:
StringBuilder sb = new(256);
And I'm sure Eric Lippert can tell us they thought of that, but he'll then apologize and say that the actual benefit was measured to be too low so they scrapped it.
Heck maybe all some of you need is a new IDE that hides things from you or lets you write your own shorthand.
Yellow Bob on June 24, 2008 3:14 PMIf var has so many people confused, what about compiler inferred types in and around lambda expressions?
var myList = new List<int>() {1, 2, 3};
var myEvens = myList.Where(x => x%2 == 0).ToList();
Q: x is what type at compile time?
A: int, but I didn't say it
Q: the anonymous function is what type at compile time?
A: Func<int, bool> but I didn't say it.
That would be Func(int, bool) ... silly Html trap.
David B on June 25, 2008 12:01 AM@John
> The program is not ill-typed. The attempt there is to use an interface reference instead of a concrete class reference. It makes perfect sense, and it won't work with vars.
He's calling a Foo1-specific method on his reference *without upcasting it*. Thus that object can *only* be typed as Foo1, whether through type inference or explicit typing. Trying to bind the typed reference to a Foo2 object after that cannot sensibly work, it's nonsensical.
> Also vshioshvili makes perfect sense. Polymorphism.
No, simply saying that doesn't explain the purpose of his last 5 paragrahs or so.
@Anvar
> it is not a real OO language
What does OO even have to do with the discussion?
> Is there such a thing as dynamic typing, or is it just a fancy way to say 'variant' under-the-covers?
Dynamic typing simply means that typechecks are performed at runtime rather than compile time (thus the dynamic part as opposed to static).
> Javascript is cooler though because you can inject methods on the fly, but only because in javascript the base object is really a hashmap.
Erm no, that's the way it works in JS, but Smalltalk and Ruby also allow injection of new methods in existing classes, and I can assure you that they don't represent classes/objects as "really a hashmap".
masklinn on June 25, 2008 12:05 AM@masklinn
>it would look for and use (if any) the lowest applicable common type.
var (c#) is much more straightfoward than that. The type you assign is the type of the declaration (period).
David B on June 25, 2008 12:39 AMJust to clarify my contrived pseudocode example: it's not correct code. The error lies at the point when a function specific to CFoo1 is called; but the compiler doesn't know that, because type inference makes it work until I try to plug another concrete class with the same interface into the variable. If I was required to assign a type to the variable at declaration explicitely, the compiler would have flagged exactly the place where the logical mistake is performed; with type inference, the compiler is complaining about a row that's perfectly alright and the error lies somewhere between that row and the var declaration (no idea where).
Once the code compiles though, var is no more dangerous than the already present implicit casting in combination with operator overloading (this is not to say that people can't break everything in very creative ways with implicit casting though).
@David B wrt refactorability: I think I expressed myself wrong. Of course I can still refactor code which unnecessarily uses internal structures of the instantiated classes; but I lose the warning flag at the variable declarations, so I will probably only find out about the problem after splitting the function. The work is essentially the same regardless of whether var is used, but with an explicit declaration you have a visual hint from the start.
"Who came up with this stuff?"
Most probably it was Anders Hejlsberg.
Diego on June 25, 2008 2:04 AMI think I understand what you're saying Tepsifles... when you say error, you mean that dev-head rules about "programming to an interface" have been broken, not machine-head rules about "assigning instances to proper reference types".
David B on June 25, 2008 6:01 AMPersonally I think var is abused such that it becomes a shortcut for writing code. I disagree with the examples you've used in stackoverflow. Allow me to point out what you said in this post, "in defense of verbosity" http://www.codinghorror.com/blog/archives/000396.html:
Saving keystrokes while writing code is a fool's economy
M on June 25, 2008 7:01 AMexcessive use of var is definitely overkill - makes code look like junk! And what about RUNTIME POLYMORPHISM? I'd Better look at wat JEff calls Redundant code which is more READABLE rather than all this var junk which makes it look like stupid javascript. Microsoft at its original creative best can only come up with cheap gimmicks (lets forget borrowing ideas for now ).
If you wanna look at typing eceonomy , I'd never use even var i'd use implicit variables like in Perl.
while(<>){if(/\d+/)print;} --> how many lines of C# or Java will it take for a 10 line perl script's equivalent??
But maintaining perl is meant only for perl exprets and a newbie would be overawed by perl thinking its a marisan laguage. I'd either use java or perl (Wen im lazy to type). No gimmicks please a var is not gonna change anyone's life upside down!!
Arun Sudhir on June 25, 2008 9:27 AMI'd like to think of var as a matter of preference and style (unlike XML, LOL).
If it's convenient to use it, use it. If you need to use the old style, you still can. Nobody's stopping anyone from using the coding style they want.
Jon Limjap on June 25, 2008 8:44 PMGot stuck on the picture showing "think" and a punch card, right along with some pursuit of happiness happy thoughts below.
Is Steve Ballmer blogging here?
BugFree on June 26, 2008 9:00 AMI think var has a valid place when it comes to extremely complex(errr... annoying) declarations.
All those "What if I want to program against an Interface?" questions are kinda stupid. If you want to do that, then USE the Interface and declare the type explicitly. The compiler will warn you about it if you dont.
var is an "option"! Its not the solution for everything. You are free to use it, but noone forces you to use it...
And
var someFuncResult = someFunc();
is bad. I have no clue what you are talking about.
A valid use is when you have a "short lived local variable that is created and assigned on declaration" or a really simple "POCO".
Also I DO know that there is a TAB key in VS...
P.s.: What annoys me more then the use of var are the names of the variables... I know its for reference only. But 2 letters is just... yuck ;)
Heiko Hatzfeld on July 1, 2008 7:47 AM@Jeff Atwood
> But why can't the 1 simply grow/size to fit?
Perhaps because of the useless internal overhead of continuosly checking ranges, overflows, etc, and upgrading types dynamically, if I undrstood right. And of course, ok about "var sb = new StringBuilder(256);"
You may say, "we have cpu and memory enough to waste it guessing the type of my 1 as it moves through the application and is crunched by my calculations". If you, as programmer, already know the type of the variable, why let the compiler or virtual machine spend cycles trying to guess it? I refer only to the case of the 1.
Seems that we like optimizing only for being more lazy, not for gaining performance. I wonder if the word "optimizing" means today the same as 10 year ago.
Is ours the civilization of careless wasting? Is wasting a good way even if we have more than enough? (remember that recent experiment: In Great Britain people could live quite well only with the surplus that supermarkets throws to the trash. Good food thrown to trash! Food, power, oil, water, whatever... If you have plenty, why not throw it? I'll ask my ancestors...)
oscar on July 4, 2008 5:49 AMvar isn't a step towards dynamically typing. It's static typing infering its type from the initialization value.
It's needed for anonymous classes and variables.
That's why you don't need to declare it's type, because you don't know or don't want to care about the type of your anonymous class.
Another thing: var variables are type safe.
var i = 1;
var j = 1.0f;
i=j;
Line 3 will produce an "implicit conversion" error.
Thank god var is quite restricted in its use. You can only declare var variables within methods.
"BufferedReader br = new BufferedReader (new FileReader(name));
Who came up with this stuff?"
What if declaration and initialization doesn't happen on the same line? What if the declaration type and the type of the assigned value aren't exactly the same?
class foo1
{
IBar br;
public foo1{int i}
{
if (i==0) br=new BufferedBar();
else br=new XmlBar();
}
}
Concerning writing redudant code:
IntelliSense? Usually I don't have to type more letters typing the actual type than typing var.
"var pi = 3.14159;"
Is pi declared as a double or a float? More important: why do I even have to think about it when declaring it as float or double right away isn't much longer?
If you use var for every possible situation, your code becomes more cryptic and unnecessary difficult to read. I think here applies your "Coding for psychopaths"-rule ;-)
"If you have a hammer, every problem looks like a nail"
zorkis on July 7, 2008 3:00 AMcomment like :
"Agreed. I use var all the time. It could be even more concise if they dropped the 'var'"
Make me ask: "Why are you coding in C#?"
Find a language that supports what you want! Try Iron python if you what to stay on the CRL/DRL.
I am keeping my "IFoo foo = new Foo();" syntax, thank you very much.
It concerns me that C# is trying to be the everything language. I give it about 3 years before no one whats to code in it anymore due to the lines be sooo blurred.
Use C# how is it supposed to be used, then use Boo, Iron python etc for more dynamic approaches.
Would you put all you javascript, css, asp.net and html in one file? I see this and being a similar scenario. 4 DIFFERENT "languages" solving different problems.
my $0.02
RhysC
| Content (c) 2009 Jeff Atwood. Logo image used with permission of the author. (c) 1993 Steven C. McConnell. All Rights Reserved. |