5

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}                                             ||
}); //<------------------------------------------------------------------||
Jan Carlo Viray
  • 11,856
  • 11
  • 42
  • 63
  • 1
    It is just special magic in C# to automatically call some methods (`Add` in particular) *after* the object has been created. –  Apr 12 '12 at 22:47
  • For the answerees: can *property initialization* be mixed with *collection initialization*? (This should be present in explaining the "outer" construct, as it could have been: `new Foo { Bar = Quz }`.) –  Apr 12 '12 at 22:51
  • @pst: No, not even in VB.NET, oddly enough... – Ry- Apr 12 '12 at 22:55
  • Related: http://stackoverflow.com/questions/459652/why-do-c-sharp-collection-initializers-work-this-way (talks about Add) –  Apr 12 '12 at 22:56

3 Answers3

8

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();
    }
}
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
7

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

Ry-
  • 218,210
  • 55
  • 464
  • 476
  • 4
    "dictionary initialization syntax" makes it sound like C# *as a language* has built-in knowledge of dictionaries. It doesn't. It'll work with *any* type which implements `IEnumerable` and has appropriate `Add` methods. – Jon Skeet Apr 12 '12 at 22:51
  • 1
    @JonSkeet: How does it recognize the fact that it's a `KeyValuePair`? – Ry- Apr 12 '12 at 22:52
  • 3
    @minitech: It doesn't. It recognizes the fact that there's an `Add(key, value)` method. See my answer for an example of this. Also note that in reality, the variable is only assigned *after* the `Add` calls - it's as if you've got a temporary variable before that. – Jon Skeet Apr 12 '12 at 22:55
  • Allow me to write in this comment :) (@edit: That's why I said "basically") – Ry- Apr 12 '12 at 22:57
  • @phoog: Jon Skeet beat you to it, because Jon Skeet beats everyone to it ;) – Ry- Apr 12 '12 at 22:59
  • 1
    Yeah, Jon Skeet apparently doesn't have the problem that I have of writing a 4-paragraph comment and then deciding to delete the last 3 paragraphs as superfluous. – phoog Apr 12 '12 at 23:02
3

Please look at Anonymous Types They allow you to do something like this:

var v = new { Amount = 108, Message = "Hello" };  
Kevin Panko
  • 8,356
  • 19
  • 50
  • 61
joshua
  • 4,118
  • 3
  • 40
  • 53