views:

1171

answers:

17
+8  Q: 

Redundancy in C#?

Take the following snippet:

List<int> distances = new List<int>();

Was the redundancy intended by the language designers? If so, why?

+10  A: 

You could always say:

 var distances = new List<int>();
Nescio
You could, but you should not! The var keyword is designed for the case where the designer does not know the type that is returned, but the compiler does - as with dynamic types in linq. It is NOT designed for lazy programmers.
BeowulfOF
Leveraging type inference is not about being lazy.
Romain Verdier
Or, embrace type inference. It's a feature, and it's there for you to use. At least, that's the case in all *other* languages sporting type inference. Also, linq does not have "dynamic types". It embraces a non-linq feature called "compiler-generated static anonymous types".
Justice
i think he meant anonymous types. but ive read a ms paper where they say not to use var in this situation. i still do when i find its more readable, like in this situation
Shawn Simon
I will always use var in this situation! The type of the object is very clear from the context at the call site. However, I would refrain from using var when calling a function that retuns the same type, as the return value is not always clear to the reader.
Nescio
A: 

Because we're addicted to compilers and compiler errors.

Brad Wilson
+1  A: 

C# is definitely getting less verbose after the addition of functional support.

Gulzar
+1  A: 

A historical artifact of static typing / C syntax; compare the Ruby example:

distances = []
Paul Betts
C# can do that too.var foo = new {"lol","what?"};
FlySwat
Struggling a bit isn't it? "var"!? "new"!? ";"!?
Brent.Longborough
Whats the ruby equivalent of creating a abstract type from a concrete constructor?
FlySwat
Ruby doesn't care about types in that way, Jonathan. It's a simple "x = SomeClass.new".
Brad Wilson
Brad, that was my point. :)
FlySwat
Good one. .
Joan Venge
+14  A: 

What's redudant about this?

List<int> listOfInts = new List<int>():

Translated to English: (EDIT, cleaned up a little for clarification)

  • Create a pointer of type List<int> and name it listofInts.
  • listOfInts is now created but its just a reference pointer pointing to nowhere (null)
  • Now, create an object of type List<int> on the heap, and return the pointer to listOfInts.
  • Now listOfInts points to a List<int> on the heap.

Not really verbose when you think about what it does.

Of course there is an alternative:

var listOfInts = new List<int>();

Here we are using C#'s type inference, because you are assigning to it immediately, C# can figure out what type you want to create by the object just created in the heap.

To fully understand how the CLR handles types, I recommend reading CLR Via C#.

FlySwat
+2  A: 

The compiler improvements for C# 3.0 (which corresponds with .Net 3.5) eliminate some of this sort of thing. So your code can now be written as:

var distances = new List<int>();

The updated compiler is much better at figuring out types based on additional information in the statement. That means that there are fewer instances where you need to specify a type either for an assignment, or as part of a Generic.

That being said, there are still some areas which could be improved. Some of that is API and some is simply due to the restrictions of strong typing.

ckramer
You could, but you should not! The var keyword is designed for the case where the designer does not know the type that is returned, but the compiler does - as with dynamic types in linq. It is NOT designed for lazy programmers.
BeowulfOF
A: 

Your particular example is indeed a bit verbose but in most ways C# is rather lean.

I'd much prefer this (C#)

int i;

to this (VB.NET)

Dim i as Integer

Now, the particular example you chose is something about .NET in general which is a bit on the long side, but I don't think that's C#'s fault. Maybe the question should be rephrased "Why is .NET code so verbose?"

Schnapple
+3  A: 

Because declaring a type doesn't necessarily have anything to do with initializing it.

I can declare

List<int> foo;

and leave it to be initialized later. Where's the redundancy then? Maybe it receives the value from another function like BuildList().

As others have mentioned the new var keyword lets you get around that, but you have to initialize the variable at declaration so that the compiler can tell what type it is.

Telos
+62  A: 

The reason the code appears to be redundant is because, to a novice programmer, it appears to be defining the same thing twice. But this is not what the code is doing. It is defining two separate things that just happen to be of the same type. It is defining the following:

  1. A variable named distances of type List<int>.
  2. An object on the heap of type List<int>.

Consider the following:

Person[] coworkers = new Employee[20];

Here the non-redundancy is clearer, because the variable and the allocated object are of two different types (a situation that is legal if the object’s type derives from or implements the variable’s type).

Jeffrey L Whitledge
@Jeffrey - nicely put. May want to edit and include that Employee inherits from Person to help clarify your explanation. Otherwise, some may think that Employee[] emp = new Person[] is valid. Well, it could be, but who knows :-)
Metro Smurf
I just noticed someone down-vote this answer and I'm curious as to why. It seems straightforward and accurate to me - am I missing something?
Matt
@Smurf - I have implemented your suggestion, thanks!
Jeffrey L Whitledge
Collections are not a great example, because the fact that you can do this with arrays is actually considered a flaw in the language design. The reason being that the compiler will let you store a non-Employee, Person-derived object in the collection, but this will fail at runtime.
Chris Ammerman
The questioner used a collection in the example, and I just went with it. I went with an array though, because generics are not covariant or contravariant in C# (at least, not yet). Whether the C# implementation of an array is flawed or not, it satisfied the purpose of the example.
Jeffrey L Whitledge
Yeah, it could just have easily used List<Person> p = new List<Employee>();
toast
+4  A: 

instead of thinking of it as redundant, think of that construct as a feature to allow you to save a line.

instead of having

List distances; distances = new List();

c# lets you put them on one line.

One line says "I will be using a variable called distances, and it will be of type List." Another line says "Allocate a new List and call the parameterless constructor".

Is that too redundant? Perhaps. doing it this way gives you some things, though

1. Separates out the variable declaration from object allocation. Allowing:

IEnumerable<int> distances = new List<int>();
// or more likely...
IEnumerable<int> distances = GetList();

2. It allows for more strong static type checking by the compiler - giving compiler errors when your declarations don't match the assignments, rather than runtime errors.

Are both of these required for writing software? No. There are plenty of languages that don't do this, and/or differ on many other points.

"Doctor! it hurts when I do this!" - "Don't do that anymore"

If you find that you don't need or want the things that c# gives you, try other languages. Even if you don't use them, knowing other ones can give you a huge boost in how you approach problems. If you do use one, great!

Either way, you may find enough perspective to allow yourself to say "I don't need the strict static type checking enforced by the c# compiler. I'll use python", rather than flaming c# as too redundant.

Philip Rieck
I suspect the poster's point wasn't about requiring type specification on variable declarations, but rather requiring them when the information is the same. This is a fair criticism, and one that the language designers took to heart in creating the "var" keyword.
Chris Ammerman
+2  A: 

The redunancy wasn't intended, per se, but was a side-effect of the fact that all variables and fields needed to have a type declaration. When you take into account that all object instantiations also mention the type's name in a new expression, you get redundant looking statements.

Now with type-inferencing using the var keyword, that redundancy can be eliminated. The compiler is smart enough to figure it out. The next C++ also has an auto keyword that does the same thing.

The main reason they introduced var, though, was for anonymous types, which have no name:

var x = new {Foo = Bar, Number = 1};
Mark Cidade
+5  A: 

As others have said: var removes the redundancy, but it has potential negative maintenance consequences. I'd say it also has potential positive maintenance consequences.

Fortunately Eric Lippert writes about it a lot more eloquently than I do: http://csharpindepth.com/ViewNote.aspx?NoteID=63 http://csharpindepth.com/ViewNote.aspx?NoteID=61

Jon Skeet
+1  A: 

Use var if it is obvious what the type is to the reader.

//Use var here
var names = new List<string>();

//but not here
List<string> names = GetNames();

From microsofts C# programing guide

The var keyword can also be useful when the specific type of the variable is tedious to type on the keyboard, or is obvious, or does not add to the readability of the code

trampster
Please do not, as var is not designed for code complifications, but for struggling with dynamic types of linq.
BeowulfOF
BeowulfOF see my edit this use of var is suggested by microsoft in there C# programming guide.
trampster
Exactly my point. Please be considerate before voting people down without knowing the finer details.
Joan Venge
Well, it reads "or does not add to the readability of the code" - so theres the point to not do that.
BeowulfOF
If for some reason you're nesting multiple generic collections, like var lotsOfLists = new List<List<List<List<int>>>>();, it is certainly more readable than the alternative.
Greg
+3  A: 

Could also do:

var distances = new List<int>();
Joan Venge
You could, but you should not! The var keyword is designed for the case where the designer does not know the type that is returned, but the compiler does - as with dynamic types in linq. It is NOT designed for lazy programmers.
BeowulfOF
No you are wrong. Where the type is obvious, it's ok to use the var, as is the case here.Do you really need to see List<int> twice?
Joan Venge
Actually read the msdn C# programming guide. The use of var to remove redundancy is suggested. And the lazy principle is a fundamental of programming. Why waste your time saying the same thing twice. It just costs your employer money.
trampster
Why is this being flagged as offensive?
Dave DeLong
A: 

I see one other problem with the using of var for laziness like that

var names = new List<string>();

If you use var, the variable named "names" is typed as List<string>, but you would eventually only use one of the interfaces inherited by List<T>.

IList<string> = new List<string>();
ICollection<string> = new List<string>();
IEnumerable<string> = new List<string>();

You can automatically use everything of that, but can you consider what interface you wanted to use at the time you wrote the code?

The var keyword does not improve readability in this example.

BeowulfOF
+1  A: 

It's only "redundant" if you are comparing it to dynamically typed languages. It's useful for polymorphism and finding bugs at compile time. Also, it makes code auto-complete/intellisense easier for your IDE (if you use one).

Kevin
A: 

In many of the answers to this question, the authors are thinking like compilers or apologists. An important rule of good programming is Don't repeat yourself!

Avoiding this unnecessary repetition is an explicit design goal of Go, for example:

Stuttering (foo.Foo* myFoo = new(foo.Foo)) is reduced by simple type derivation using the := declare-and-initialize construct.

Greg Bacon