This project is read-only.

Dictionary initializers semantic

Topics: C# Language Design
Oct 10, 2014 at 1:21 PM
Currently this code:
using System;
using System.Collections.Generic;

class Foo : Dictionary<int, Foo> {
    public int A { get; set; }
    public int B { get; set; }
    
    int M() {
        var foo = new Foo {
            [M()] = { A = 1, B = 2 }
        };
        
        return 42;
    }
}
Is equivalent to C# 5.0 code like this:
using System;
using System.Collections.Generic;

class Foo : Dictionary<int, string> {
    public int A { get; set; }
    public int B { get; set; }

    int M() {
        var tmp = new Foo();
        tmp[M()].A = 1; // <=
        tmp[M()].B = 2; // <=
        var foo = tmp;

        return 42;
    }
}
As we can see, currently evaluation of dictionary initializer argument happens twice, possibly resulting in side-effects duplication. This fact isn't clear for user - dictionary initializer looks like linear code, not sure anyone really expects re-evaluation of argument happening per every nested member initializer.

I'm pretty sure this effect is caused by design chosen for nested initializers long before - every nested object/collection initializer member always evaluates whole chain of initialized members (new A{B={C={1,2}}} produces a.B.C.Add(1); a.B.C.Add(2);).

From IDE tools developer perspective, control flow graph for current design of dictionary initializers looks too weird to be truth :)

What do you think, Roslyn team?
Oct 10, 2014 at 3:07 PM
Wow, I would not expect that behavior at all.

As for nested list initialization, I just tested that and it does repeat access to the C property multiple times but not to the B property. It works out to the following:
Foo temp1 = new Foo();
A temp2 = new A();
B temp3 = new B();
temp3.C.Add("a");
temp3.C.Add("b");
temp3.C.Add("c");
temp2.B = temp3;
temp1.A = temp2;
Foo foo = temp1;
I wonder why that was chosen as opposed to accepting the result of the C property to a temporary variable and then calling the Add method on that rather than constantly accessing the property.
Oct 13, 2014 at 4:29 PM
I don't have better than your "wow" reaction. That was mine too.

Even though I don't see myself using an expression with a side effect here, multiple evaluations seem quite wrong. I don't see any other place in the language where it's the case. I'm pretty curious to know why this was preferred to a temporary.