What C# feature allows the use of an “object literal” type notation?
-
31-05-2021 - |
Question
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} ||
}); //<------------------------------------------------------------------||
La solution
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 toGetEnumerator
- 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();
}
}
Autres conseils
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.
Please look at Annonymous Types They allow you to do something like this:
var v = new { Amount = 108, Message = "Hello" };