Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What C# feature allows the use of an "object literal" type notation?

I'm coming from JavaScript, and I know that { } is an object literal, not needing to require the new Object call; I'm wondering if it's the same with C# in the {"id",id}, {"saveChangesError",true} part.

I know there are two C# features in here, care to explain to me more about what they are?

new RouteValueDictionary()
{ //<------------------------------[A: what C#  feature is this?] -------||
   {"id",id}, //<------------------[B: what C# feature is this also?]    ||
   {"saveChangesError",true}                                             ||
}); //<------------------------------------------------------------------||
like image 716
Jan Carlo Viray Avatar asked Apr 12 '12 22:04

Jan Carlo Viray


2 Answers

It's a single feature - collection initializers. Like object initializers, it can only be used as part of an object initialization expression, but basically it calls Add with whatever arguments are present - using braces to specify multiple arguments, or single arguments at a time without the extra braces, e.g.

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

See section 7.6.10.3 of the C# 4 spec for more information.

Note that the compiler requires two things of a type for it to be used for collection initializers:

  • It must implement IEnumerable, although the compiler doesn't generate any calls to GetEnumerator
  • It must have appropriate overloads for an Add method

For example:

using System;
using System.Collections;

public class Test : IEnumerable
{
    static void Main()
    {
        var t = new Test
        {
            "hello",
            { 5, 10 },
            { "whoops", 10, 20 }
        };
    }

    public void Add(string x)
    {
        Console.WriteLine("Add({0})", x);
    }

    public void Add(int x, int y)
    {
        Console.WriteLine("Add({0}, {1})", x, y);
    }

    public void Add(string a, int x, int y)
    {
        Console.WriteLine("Add({0}, {1}, {2})", a, x, y);
    }

    IEnumerator IEnumerable.GetEnumerator()        
    {
        throw new NotSupportedException();
    }
}
like image 145
Jon Skeet Avatar answered Sep 19 '22 14:09

Jon Skeet


That's collection initialization syntax. This:

RouteValueDictionary d = new RouteValueDictionary()
{                             //<-- A: what C#  feature is this?
   {"id",id},                 //<-- B: what C# feature is this also?    
   {"saveChangesError",true}
});

is basically equivalent to this:

RouteValueDictionary d = new RouteValueDictionary();
d.Add("id", id);
d.Add("saveChangesError", true);

The compiler recognizes the fact that it implements IEnumerable and has an appropriate Add method and uses that.

See: http://msdn.microsoft.com/en-us/library/bb531208.aspx

like image 40
Ry- Avatar answered Sep 20 '22 14:09

Ry-