Home > Net >  New syntax to set readonly property outside constructor
New syntax to set readonly property outside constructor

Time:05-02

I needed to write a quick POST request in C# and decided to copy-paste a random piece of code from the internet. Everything worked fine however the syntax is so strange that I did not expect it to compile at all:

var request = new HttpRequestMessage
{
    Method = HttpMethod.Post,
    RequestUri = new Uri("https://www.random-api.com/api/random"),
    Headers =   {
        { "Accept-Encoding", "application/gzip" },
        { "Content-Type", "text/plain" },
    },
    Content = new FormUrlEncodedContent(new Dictionary<string, string>
    {
        { "q", "Lorem ipsum" },
    }),
};

The part that I don't understand is:

Headers =   {
    { "Accept-Encoding", "application/gzip" },
    { "Content-Type", "text/plain" },
},

One of the things that bugs me is the fact that Headers is a readonly property that is being set outside the HttpRequestMessage's constructor and the other thing is the value that is used - {{"key", "value"}} much like a Dictionary<string,string> that is instantiated with an initial value.

CodePudding user response:

This is called inline initialization of objects using an object initializer. It's possible because the HttpRequestMessage class has a public no-arg constructor and the properties being set have public access modifiers.

You can read more about this technique over at Microsoft's documentation of this feature: https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/how-to-initialize-objects-by-using-an-object-initializer

Here's the documentation for the HttpRequestMessage class: https://docs.microsoft.com/en-us/dotnet/api/system.net.http.httprequestmessage?view=net-6.0

CodePudding user response:

What you see there done with the Headers property is called a "collection initializer". As per documentation:

var moreNumbers = new Dictionary<int, string>
{
    {19, "nineteen" },
    {23, "twenty-three" },
    {42, "forty-two" }
};

This initializer example calls Add(TKey, TValue) to add the three items into the dictionary.

Thus, all that is required for this particular flavor of a collection initializer to work is that the object to be initialized offers an Add(TKey, TValue) method. (The authoritative and more detailed specification can be found in the C# language specification, §11.7.15.4 Collection initializers.)

With respect to your question, the Headers property is of type HttpRequestHeaders.

So, does HttpRequestHeaders have a Add(string, string) method required for this collection initializer to work? Yes, it does (declared by HttpRequestHeaders' base class HttpHeaders).

  • Related