Collection Initializers

File this in my learn something new every day bucket. I received an email from Steve Maine after he read a blog post in which I discuss the anonymous object as dictionary trick that Eilon came up with.

He mentioned that there is an object initializer syntax for collections and dictionaries.

var foo = new Dictionary<string, string>()
{
  { "key1", "value1" },
  { "key2", "value2" }
};

That’s pretty nice!

Here is a post by Mads Torgersen about collections and collection initializers.

Naturally someone will mention that the Ruby syntax is even cleaner (I know, because I was about to say that).

However, suppose C# introduced such syntax:

var foo = {"key1" => "value1", 2 => 3};

What should be the default type for the key and values? Should this always produce Dictionary<object, object>? Or should it attempt type inference for the best match? Or should there be a funky new syntax for specifying types?

var foo = <string, object> {"key1" => "value1", "2" => 3};

My vote would be for type inference. If the inferred type is not the one you want, then you have to resort to the full declaration.

Then again, the initializer syntax that does exist is much better than the old way of doing it, so I’m happy with it for now. In working with a statically typed language, I don’t expect that all idioms for dynamic languages will translate over in as terse a form.

Check out this use of lambda expressions by Alex Henderson to create a hash that is very similar in style to what ruby hashes look like. Thanks Sergio for pointing that out in the comments.

What others have said

Requesting Gravatar... Scott Jan 06, 2008 1:38 PM
# re: Collection Initializers
The C# initializer is very close to how ObjectiveC initWithObjectsAndKeys initializer works. Pythons dictionary allows you to initialze them in a similar manner to Ruby.
http://docs.python.org/tut/node7.html#SECTION007500000000000000000

The ability to create dictionaries using tuples is pretty cool though. Very LISPy.

Pythons syntax in this case is probably the cleanest. I wonder if we'll end up mixing and mashing language features once the DLR is out. building dictionaries and dealing with data in IronRuby/IronPython but building business logic in C#?
Requesting Gravatar... Sergio Pereira Jan 06, 2008 3:36 PM
# re: Collection Initializers
Have you checked the
Hash trick by Alex Henderson. Check the comments too.
Back to your question, I'd vote for a dual approach. If no type is specified, then infer from the keys and demand that they be of the same type. When the types are specified, well that requires no explanation really.
Requesting Gravatar... Thibaut Barrère Jan 06, 2008 7:05 PM
# re: Collection Initializers
I'd vote for type inference as well (maybe because I like the Ruby syntax too!).

FWIW: for unit tests at least and when the generics are not available, I tend to use a little helper (static function for instance with params object arg) to allow calls like:

IDictionary order = Hash("price",200.0,"quantity",24);

Not as neat but saves a lot of typing already.
Requesting Gravatar... Rik Hemsley Jan 07, 2008 2:00 AM
# re: Collection Initializers

Ruby has a small advantage with type inference. It can assume that a number
is of class Fixnum (if it fits into one) safe in the knowledge that it will
be automatically changed into a Bignum later, if it becomes necessary.



C# doesn't have this luxury. It's not possible to guess at the correct
type to give a number.



Sergio said:


If no type is specified, then infer from the keys and demand that they be of the same type.

It's possible to infer from the keys in the above example that string should be used, but, given e.g. { "count", 42 }, what should be used for value? What if you pick something too small and I want to set 'count' to a larger number later?



I suppose it wouldn't be terrible to assume 'long' in the above example, but
there are bound to be complaints about that from people who need/want the
smallest possible storage.



Requesting Gravatar... Jason Haley Jan 07, 2008 6:50 AM
# Interesting Finds: January 7, 2008
Requesting Gravatar... Bitter Coder Jan 07, 2008 12:50 PM
# mucking about with hashes...
Requesting Gravatar... Scott Hanselman's Computer Zen Jan 08, 2008 11:43 AM
# The Weekly Source Code 12 - Back in Black Edition
Requesting Gravatar... ASPInsiders Jan 08, 2008 12:10 PM
# The Weekly Source Code 12 - Back in Black Edition
It's been a while since the last Weekly Source Code , but I have the holidays and the preponderance of
Requesting Gravatar... Diago.co.za Jan 09, 2008 10:20 AM
# Early start to the year
Early start to the year
Requesting Gravatar... Filini Jan 14, 2008 1:43 AM
# re: Collection Initializers
I think type inference might not always be the best choice.
Suppose you have:

Class1 : Class2

and

Class2 : Class3

var foo = { {myClass1 = "foo1"}, {myClass2 = "foo2"} };

probably the inferred type for my dictionary would be <Class2, String>

and I wouldn't be able to do

foo.Add( { myClass3, "foo3"} );

So in this case I would probably stick with an explicit declaration of Dictionary<Class3, String>

PS: Do correct me if I'm wrong, I don't know how type inference exactly works in such a situation; lately I have been reading Eric Lippert's posts about immutability and inference, and I'm trying to get a grasp of it :P
Requesting Gravatar... Haacked Jan 14, 2008 9:24 AM
# re: Collection Initializers
@Filini That's easy enough to fix. If you intend for the inferred type to be Class3, just do this:


var foo = {{myClass1, "foo1"}, {(Class3)myClass2, "foo2"}};


Or use the full syntax. :)
Requesting Gravatar... Filini Jan 15, 2008 12:53 AM
# re: Collection Initializers
Yep. And I guess the full syntax would be cleaner (and easier to read) than the cast to Class3.

Sometimes, these shortening syntactic sugars make the code cleaner to the writer, but not to the other developers of the team. This must always be kept in mind.

What do you have to say?

(will show your gravatar)
Please add 8 and 2 and type the answer here: