tags:

views:

1111

answers:

4

You can initialize an array like this:

int [ ] arr = { 1, 2, 3, 4, 5 }; 

but List<T> doesn't allow this:

List<int> list = { 1, 2, 3, 4, 5 }; 

What's the reason behind this?

After all both allow this:

int [ ] arr = new int [ ] { 1, 2, 3, 4, 5 }; 

List<int> list = new List<int> { 1, 2, 3, 4, 5 }; 

Also why it's not possible to do this with a LinkedList<T>?:

LinkedList<int> ll = new LinkedList<int>() { 1, 2, 3 };

Update

Thanks guys. Just saw the replies. I wanted to pick several answers but it didn't let me so.

Why does the LinkedList has an Add method though explicit implementation? Will this likely be fixed? Because problems like this will just snowball into bigger ones when they are overlooked, right?

Thanks.

+1  A: 

I never realized you can't use collection initialization with a LinkedList(T), but it seems logical since it has no "Add" method, it instead has "AddFirst" and "AddLast". Collection initialization uses the "Add"-method.

Patrik Hägne
+1  A: 

Because making arrays is built into the language, for example int[], float[], WhateverClassHere[]. This syntax is for making arrays, not initializing lists.

In your example, you are making an array of ints. Using that syntax to add values to a list shouldnt work because List isnt an array.

Sean James
You can instantiate arrays of complex types like this, it has nothing to do with that. The question is why the syntax for creating an array differs from how you do collection initialization.
Patrik Hägne
Oh, I didnt realize that.
Sean James
+10  A: 

Your first sample is the standard language syntax for initializing an array of integers. The left-hand value evaluates to int[]. In the second sample you are attempting to assign an int[] to a List<int>. The assignment operator doesn't support this as they are different types. A List<int> is not an array of type int. As you say, though, there is a constructor for List<int> that does take an int[] as an argument and the new syntactic sugar added in C# 3.0 allows you the convenience of using { } to add members to the collection defined by the default constructor.

As @Patrik says, this won't work for LinkedList because it doesn't define the Add() method as part of its interface (there is an explicit implementation of ICollection.Add) so the syntactic sugar won't work.

There is an easy work-around for LinkedList, however.

public class LinkedListWithInit<T> : LinkedList<T>
{
    public void Add( T item )
    {
        ((ICollection<T>)this).Add(item);
    }
}

LinkedList<int> list = new LinkedListWithInit<int> { 1, 2, 3, 4, 5 };
tvanfosson
Heh beat me to it, but succinctly put. +1
Kev
I think it's a bit weird though, since the LinkedList(T) acutally does have an Add-method, implemented for the ICollection(T)-interface. It's explicitly implemented so it's not public unless you cast the list to an ICollection(T), but I think it should be valid.
Patrik Hägne
But there's no way to cast it to ICollection between creating it attempting to initialize it so the explicitly implemented interface is useless. I've updated my answer to clarify this.
tvanfosson
What I meant is that I think that the compiler should be smart enough to find the interface-Add. The Add-method of LinkedList(T) should've never been explicitly implemented, but that's a whole other issue.
Patrik Hägne
It probably doesn't look through all the types that are implemented by the type when looking for the method. I'd need to think about all the use cases before I could say whether that would be reasonable. I'm not sure why it isn't implemented directly either; it would seem reasonable that way.
tvanfosson
Stuff that is overlooked like this bothers me simply because they aren't gonna fix it for backwards compatibility, right, whereas shouldn't class libraries be updated all the time for the better?
Joan Venge
+3  A: 

Here is what the C# 3.0 Language Spec has to say on the subject:

The following is an example of an object creation expression that includes a collection initializer:

List<int> digits = new List<int> { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

The collection object to which a collection initializer is applied must be of a type that implements System.Collections.IEnumerable or a compile-time error occurs. For each specified element in order, the collection initializer invokes an Add method on the target object with the expression list of the element initializer as argument list, applying normal overload resolution for each invocation. Thus, the collection object must contain an applicable Add method for each element initializer.

That makes sense when you think about it. The compiler makes sure you are working on an enumerable type that implements an Add function (through which it does the initialization).

Jason Jackson