What is the name of the syntax used in the Headers property?
Headers is defined as public HttpRequestHeaders Headers {get;}
.
It hurts my head that the left side of the expression is not a setter.
I'm not finding it in hidden features of c# or History of C#
var tokenRequest = new HttpRequestMessage
{
Method = HttpMethod.Post,
RequestUri = new Uri("http://localhost"),
Headers = {
{ HttpRequestHeader.Authorization.ToString(), "abc123" },
{ HttpRequestHeader.ContentType.ToString(), "application/x-www-form-urlencoded" }
},
Content = new FormUrlEncodedContent(new Dictionary<string, string> { ["grant_type"] = "client_credentials" })
};
CodePudding user response:
I'm not sure if there's an official name for it, but I've seen it being called collection initializer "duck typing", done implicitly by the compiler. The compiler will look for a suitable Add
method implemented by the type, as well as the type has to implement the IEnumerable
interface. HttpRequestMessage.Headers
ultimately fits both these criteria, and even though the property has only a getter, the compiler will translate the collection initializer into consecutive "Add" calls right after the object has been created.
CodePudding user response:
This is collect Object Intializer syntax and Collection Initializer syntax.
It hurts my head that the left side of the expression is not a setter.
Using a collection initializer you can set the value of a property during the constructor even with no set
defined. Specifically for a collection, the documentation linked above says this:
Collection initializers let you specify one or more element initializers when you initialize a collection type that implements IEnumerable and has Add with the appropriate signature as an instance method or an extension method.
This can be really strange (or cool, depending on how you look at it), because you can build your own Add()
extension method for almost any type and use it to do some really interesting things.
Also remember, when using a property that is also a collection or other property, you do not need a set
to call methods or change property values within this object or collection. Instead, you first get
the reference to the collection, and then use whatever access is provided by that nested property.
For example, let's say you have a variable tokenRequest
that has a property Headers
of type HttpRequestHeaders
. The HttpRequestHeaders
type in turn has an Add()
method. To call that method you first get
the reference to the Headers
property and the call method on that reference. No set
is ever used or needed, and yet you still managed to change a property that only has get
defined.
Collection initializers take advantage of this.