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

3

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}                                             ||
}); //<------------------------------------------------------------------||
Comfit answered 12/4, 2012 at 22:45 Comment(4)
It is just special magic in C# to automatically call some methods (Add in particular) after the object has been created.Belt
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 }.)Belt
@pst: No, not even in VB.NET, oddly enough...Etalon
Related: #460152 (talks about Add)Belt
R
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();
    }
}
Rooney answered 12/4, 2012 at 22:48 Comment(3)
Let's have a link to MSDN documentation in the answer, at least. :)Spurtle
@DanJ: Yeah, I'm getting there :)Rooney
@JonSkeet Applying the principles of Agile to answering StackOverflow questions, eh? Hmm. ;)Spurtle
E
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

Etalon answered 12/4, 2012 at 22:48 Comment(6)
"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.Rooney
@JonSkeet: How does it recognize the fact that it's a KeyValuePair?Etalon
@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.Rooney
Allow me to write in this comment :) (@edit: That's why I said "basically")Etalon
@phoog: Jon Skeet beat you to it, because Jon Skeet beats everyone to it ;)Etalon
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.Gawlas
L
4

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

var v = new { Amount = 108, Message = "Hello" };  
Lohrman answered 8/3, 2021 at 4:18 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.