Aliq Qim
Aliq Qim

Reputation: 136

Is this C# syntax possible?

In one of C# projects I've worked with I've met following piece of code:

var session = new Session
{
    Application = /*!!!*/
    {
        PublicApplicationId = appId
    },
    LastActivityTime = DateTime.Now - TimeSpan.FromTicks(1)
};

I met it some time ago, but only now I got my hands on it.

I don't have access to the sources anymore, so don't know what Session class was meant.

But I'm wondering how is it possible syntactically?

Why is the Application property initialized by just some JSON-like object in braces?

Any Ideas?

addition: /!!!/ - I put this comment to mark the strange place. there were nothing there, no "new SomeClass"

UPD: thanks for the answer! here is a more human-readable description of this feature: https://fuqua.io/blog/2020/12/a-lesser-known-csharp-feature-nested-object-initializers/

Upvotes: 2

Views: 124

Answers (3)

F_CIL
F_CIL

Reputation: 35

In the comments, there isn't a 'new', so maybe the property Application has been new. like this:

namespace ConsoleAppForTest;

internal class ObjectA
{
    public string Name { get; set; }
}

internal class ObjectB
{
    public ObjectA ObjA { get; set; } = new ObjectA();
    public int Num { get; set; }
}

public class Entry
{
    public static void Main()
    {
        ObjectB b = new ObjectB
        {
            ObjA =
            {
                Name = "MyTest"
            },
            Num = 1
        };

        Console.WriteLine(b.ObjA.Name); // MyTest
        Console.WriteLine(b.Num); // 1
    }
}

Just like shingo said before, it do the same thing as session.Application.PublicApplicationId = appId;

Upvotes: 1

shingo
shingo

Reputation: 27011

The syntax without new keyword is called nested object initializer, and I can only find the footprint in the specification

A member initializer that specifies an object initializer after the equals sign is a nested object initializer, i.e., an initialization of an embedded object. Instead of assigning a new value to the field or property, the assignments in the nested object initializer are treated as assignments to members of the field or property. Nested object initializers cannot be applied to properties with a value type, or to read-only fields with a value type.

So the Application prop doesn't get initialized, the code is equivalent to

session.Application.PublicApplicationId = appId;

Upvotes: 6

ProgrammingLlama
ProgrammingLlama

Reputation: 38757

Your code would initialize an object like this:

public class Session
{
    public Session()
    {
        this.Application = new Application();
    }

    public Application Application { get; }
    public DateTime LastActivityTime { get; set; }
}

public class Application
{
    public int PublicApplicationId { get; set; }
}

See how the Application property isn't settable? It's a read-only property, so you can't assign a new value to it. You must use the existing value set by the constructor. Therefore, the syntax you've observed allows you to use the object initializer pattern to set Application's variables.

For more information, see Object Initializers in the documentation.

Upvotes: 3

Related Questions