Take the following snippet:
List<int> distances = new List<int>();
Was the redundancy intended by the language designers? If so, why?
Take the following snippet:
List<int> distances = new List<int>();
Was the redundancy intended by the language designers? If so, why?
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:
List<int>
. 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).
What's redudant about this?
List<int> listOfInts = new List<int>():
Translated to English: (EDIT, cleaned up a little for clarification)
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#.
You could always say:
var distances = new List<int>();
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
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.
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.
Could also do:
var distances = new List<int>();
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.
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};
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).
A historical artifact of static typing / C syntax; compare the Ruby example:
distances = []
C# is definitely getting less verbose after the addition of functional support.
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
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?"
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.
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.
Because we're addicted to compilers and compiler errors.