web-dev-qa-db-ger.com

Ausführungsreihenfolge des C # -Konstruktors

In C #, wenn Sie das tun

Class(Type param1, Type param2) : base(param1) 

wird zuerst der Konstruktor der Klasse ausgeführt und dann der Superklassenkonstruktor aufgerufen oder wird zuerst der Basiskonstruktor aufgerufen?

112
webdreamer

Die Reihenfolge ist:

  • Mitgliedsvariablen werden für alle Klassen in der Hierarchie auf Standardwerte initialisiert

Beginnen Sie dann mit der am besten abgeleiteten Klasse:

  • Variableninitialisierer werden für den am häufigsten abgeleiteten Typ ausgeführt
  • Die Konstruktorkettung ermittelt, welcher Basisklassenkonstruktor aufgerufen werden soll
  • Die Basisklasse wird initialisiert (rekursiv all das :)
  • Die Konstruktorkörper in der Kette in dieser Klasse werden ausgeführt (beachten Sie, dass es mehrere geben kann, wenn sie mit Foo() : this(...) etc. Verkettet sind

Beachten Sie, dass in Java die Basisklasse initialisiert wird , bevor Variableninitialisierer ausgeführt werden. Wenn Sie jemals einen Code portieren, ist dies ein wichtiger Unterschied, über den Sie Bescheid wissen sollten :)

Ich habe eine Seite mit mehr Details wenn Sie interessiert sind.

161
Jon Skeet

Es wird zuerst der Basiskonstruktor aufgerufen. Denken Sie auch daran, dass der leere Konstruktor der Basis aufgerufen wird, wenn Sie :base(param1) nicht nach Ihrem Konstruktor einfügen.

48

Der Konstruktor der Basisklasse wird zuerst aufgerufen.

12
tanascius

Ich bin nicht sicher, ob dies ein Kommentar/eine Antwort sein soll, aber für diejenigen, die anhand von Beispielen lernen, veranschaulicht diese Geige auch die Reihenfolge: https://dotnetfiddle.net/kETPKP

using System;

// order is approximately
/*
   1) most derived initializers first.
   2) most base constructors first (or top-level in constructor-stack first.)
*/
public class Program
{
    public static void Main()
    {
        var d = new D();
    }
}

public class A
{
    public readonly C ac = new C("A");

    public A()
    {
        Console.WriteLine("A");
    }
    public A(string x) : this()
    {
        Console.WriteLine("A got " + x);
    }
}

public class B : A
{
    public readonly C bc = new C("B");

    public B(): base()
    {
        Console.WriteLine("B");
    }
    public B(string x): base(x)
    {
        Console.WriteLine("B got " + x);
    }
}

public class D : B
{
    public readonly C dc = new C("D");

    public D(): this("ha")
    {
        Console.WriteLine("D");
    }
    public D(string x) : base(x)
    {
        Console.WriteLine("D got " + x);
    }
}

public class C
{
    public C(string caller)
    {
        Console.WriteLine(caller + "'s C.");
    }
}

Ergebnis:

D's C.
B's C.
A's C.
A
A got ha
B got ha
D got ha
D
7
user420667

[Edit: in der Zeit, die ich brauchte, um zu antworten, hatte sich die Frage total verändert].

Die Antwort ist, dass es zuerst die Basis anruft.

[Ursprüngliche Antwort auf die alte Frage unten]

Fragen Sie, wann Sie das "Basis" -Bit des Konstruktoraufrufs ausführen würden?

In diesem Fall würden Sie einen Aufruf an die Konstruktorbasis "verketten", wenn die Klasse von einer anderen Klasse mit folgendem Konstruktor abgeleitet ist:

  public class CollisionBase
    {
        public CollisionBase(Body body, GameObject entity)
        {

        }
    }

    public class TerrainCollision : CollisionBase
    {
        public TerrainCollision(Body body, GameObject entity)
            : base(body, entity)
        {

        }
    }

In diesem Beispiel leitet sich TerrainCollision von CollisionBase ab. Durch diese Verkettung der Konstruktoren wird sichergestellt, dass der angegebene Konstruktor in der Basisklasse mit den angegebenen Parametern aufgerufen wird und nicht der Standardkonstruktor (falls vorhanden).

1
Rob Levine

Ihre Frage ist etwas unklar, aber ich gehe davon aus, dass Sie Folgendes fragen wollten

Wann rufe ich den Basiskonstruktor für mein XNA-Objekt auf, anstatt den impilict-Standardkonstruktor zu verwenden?

Die Antwort darauf hängt in hohem Maße von Ihrem Szenario und dem zugrunde liegenden Objekt ab. Könnten Sie im Folgenden etwas näher erläutern?

  • Was ist das Szenario
  • Was ist der Typ des Basisobjekts von TerrainCollision?

Meine beste Antwort ist jedoch, dass Sie in dem Fall, in dem Sie Parameter haben, die mit den Parametern des Konstruktors der Basisklasse übereinstimmen, diese mit ziemlicher Sicherheit aufrufen sollten.

0
JaredPar

Der Konstruktormechanismus ist viel besser, da die Anwendung keine Konstruktorkettung mehr verwenden muss. Wenn Sie die Anwendung erweitern, können Sie durch Vererbung minimale Codeänderungen vornehmen. Jon Skeets Article

0
lloydom