Department of Declaration Redundancy Department

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


This is a companion discussion topic for the original blog entry at: http://www.codinghorror.com/blog/2008/06/department-of-declaration-redundancy-department.html

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

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

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

Sorry, but this was a lame post.

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

@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).

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

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

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.

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

FooVector some_foos;

rather than
std::vectorref_ptrFoo some_foos;

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

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

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

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

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

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

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

“…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

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

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

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

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

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

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

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

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

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?

  1. var url = "a href="http://tinyurl.com/5pfvvy"http://tinyurl.com/5pfvvy/a";

  2. var maxentries = 5;

  3. var pi = 3.14159;

  4. string or url? is it obvious? no.

  5. int or long? is it obvious? no.

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