Collection Initializers

0 comments suggest edit

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.

Technorati Tags: C#,Object Initializers,Collection Initializers

Found a typo or error? Suggest an edit! If accepted, your contribution is listed automatically here.



10 responses

  1. Avatar for Scott
    Scott January 6th, 2008

    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.
    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#?

  2. Avatar for Sergio Pereira
    Sergio Pereira January 6th, 2008

    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.

  3. Avatar for Thibaut Barr&#232;re
    Thibaut Barr&#232;re January 6th, 2008

    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.

  4. Avatar for Rik Hemsley
    Rik Hemsley January 6th, 2008

    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.

  5. Avatar for ASPInsiders
    ASPInsiders January 8th, 2008

    It's been a while since the last Weekly Source Code , but I have the holidays and the preponderance of

  6. Avatar for January 8th, 2008

    Early start to the year

  7. Avatar for Filini
    Filini January 13th, 2008

    I think type inference might not always be the best choice.
    Suppose you have:
    Class1 : Class2
    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

  8. Avatar for Haacked
    Haacked January 13th, 2008

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

  9. Avatar for Filini
    Filini January 14th, 2008

    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.

  10. Avatar for ruby
    ruby March 8th, 2015

    Ha ha ha! NICKELS! But I'd have to remove the sandwich.