Laden...

Warum kompiliert diese Objektinitialisierung (und wird sogar vom VS Intellisense so unterstützt)?

Erstellt von unconnected vor 10 Jahren Letzter Beitrag vor 10 Jahren 1.627 Views
unconnected Themenstarter:in
849 Beiträge seit 2006
vor 10 Jahren
Warum kompiliert diese Objektinitialisierung (und wird sogar vom VS Intellisense so unterstützt)?

Warum kompiliert das und wird sogar vom VS Intellisense so unterstützt?


class Program
    {
static void Main(string[] args)
        {
            var x = new Test() {Mopped =
                {
                    IrgendEtwas = "Test"
                }
            };
        }

        public class Test
        {
            public Test2 Mopped { get; set; }
        }

        public class Test2
        {
            public string IrgendEtwas { get; set; }
        }
}

Ich habe 1 1/2 Stunden gebraucht um rauszubekommen warum dieser Schnippsel mit einer NullReference fliegt. Weil ich einfach nicht gesehen habe das ein new Test2() fehlt.

Also was passiert hier? ich weise dem Property ein Anonymes Object zu.. warum kompiliert das?
Und warum die NullRefererenz? 8o

edith: Ok, ich schätze die NullReference kommt, weil ich ein Property eines Test2 Objects aufrufe, das aber nie existiert hat. Weil kein new Aufgerufen wird.. bleibt aber trotzdem die Frage warum das kompiliert.

Grüße

49.485 Beiträge seit 2005
vor 10 Jahren

Hallo unconnected,

klarer wird es, wenn man sich im Reflector anschaut, wie die Objektinitialisierung (die ja reine Compiler-Magic ist) aufgelöst wird.

private static void Main(string[] args)
{
    Test <>g__initLocal0 = new Test();
    <>g__initLocal0.Mopped.IrgendEtwas = "Test";
    Test x = <>g__initLocal0;
}

Wenn man sich nun vorstellt, dass es in der Klasse Test einen Konstruktor gibt, der Mopped auf new Test2 () initalisiert, dann würde der Code ohne NullReferenceException laufen. Insofern gibt es also Fälle, in denen so eine Konstruktion Sinn macht. Es handelt sich also um ein korrektes Sprachkonstrukt. Dass IntelliSense das unterstützt, ist dann die logische Folge.

herbivore

3.511 Beiträge seit 2005
vor 10 Jahren

ich weise dem Property ein Anonymes Object zu

Nein, tust du nicht, denn ein typisierten Objekt, kann man kein anonymes zuweisen 😃. Die Syntax die du verwendest ist reiner syntaktischer Zucker. Das nennt sich Object and Collection Initializer. Ausgeschrieben sieht es so aus:


var x = new Test();
x.Mopped.IrgendEtwas = "Test";

Was auch sofort erklärt, warum eine NullReferenceException fliegt.

Die Objekte werden in der angegebenen Reihenfolge erzeugt (constructor) und die Werte werden zugewiesen. Wenn du Test erweiterst um


public class Test
{
    public Test()
    {
        Mopped = new Test2();
    }

    public Test2 Mopped { get; set; }
}

funktioniert es, da dann die Reihenfolge (natürlich nur in etwas) so aussieht.


var x = new Test();
x.Mopped = new Test2();
x.Mopped.IrgendEtwas = "Test";

So in der Art sieht es dann im IL aus. Das kann man sich aber selber anschauen. Ist halt nur vereinfacht dargestellt.

"Jedes Ding hat drei Seiten, eine positive, eine negative und eine komische." (Karl Valentin)

unconnected Themenstarter:in
849 Beiträge seit 2006
vor 10 Jahren

Hmm, mir war nur nicht klar das ich einen Object Initializer von etwas aufrufen kann, was ich nicht direkt vorher erzeugt habe. (Und somit habe ich den inneren Initializer nicht als solchen wahrgenommen)

Das ganze funktioniert wohl nur wenn ich mich schon in einem Initializer befinde.

den das geht ja auch nicht (zum Glück)

x.Mopped = {IrgendEtwas = "Test"}

Grüße und Danke für den kleinen Augenöffner.