it-swarm.com.de

Basiskonstruktor in C # - Was wird zuerst aufgerufen?

Was wird zuerst aufgerufen - der Basiskonstruktor oder "anderes Zeug hier"?

public class MyExceptionClass : Exception
{
    public MyExceptionClass(string message, string extrainfo) : base(message)
    {
        //other stuff here
    }
}
115
Mike Comstock

Der Basiskonstruktor wird zuerst aufgerufen.

versuch es:

public class MyBase
{
  public MyBase()
  {
    Console.WriteLine("MyBase");
  }
}

public class MyDerived : MyBase
{
  public MyDerived():base()
  {
    Console.WriteLine("MyDerived");
  }
}
106
craigb

Basisklassenkonstruktoren werden vor abgeleiteten Klassenkonstruktoren aufgerufen, aber abgeleitete Klasseninitialisierer werden vor Basisklasseninitialisierern aufgerufen. Z.B. im folgenden Code:

public class BaseClass {

    private string sentenceOne = null;  // A

    public BaseClass() {
        sentenceOne = "The quick brown fox";  // B
    }
}

public class SubClass : BaseClass {

    private string sentenceTwo = null; // C

    public SubClass() {
        sentenceTwo = "jumps over the lazy dog"; // D
    }
}

Ausführungsreihenfolge ist: C, A, B, D.

Schauen Sie sich diese 2 MSDN-Artikel an:

142
Sam Meldrum

Versuche dich nicht daran zu erinnern, versuche dir selbst zu erklären, was passieren muss. Stellen Sie sich vor, Sie haben eine Basisklasse mit dem Namen Animal und eine abgeleitete Klasse mit dem Namen Dog. Die abgeleitete Klasse fügt der Basisklasse einige Funktionen hinzu. Wenn der Konstruktor der abgeleiteten Klasse ausgeführt wird, muss daher die Basisklasseninstanz verfügbar sein (damit Sie ihr neue Funktionen hinzufügen können). Deshalb werden die Konstruktoren von der Basis zu den abgeleiteten ausgeführt, die Destruktoren jedoch in umgekehrter Reihenfolge - zuerst die abgeleiteten Destruktoren und dann die Basisdestruktoren.

(Dies ist vereinfacht, aber es soll Ihnen helfen, diese Frage in Zukunft zu beantworten, ohne sich dies tatsächlich merken zu müssen.)

34
David Pokluda

Tatsächlich wird der Konstruktor der abgeleiteten Klasse zuerst ausgeführt, aber der C # -Compiler fügt einen Aufruf des Konstruktors der Basisklasse als erste Anweisung des Konstruktors der abgeleiteten Klasse ein.

Also: Die abgeleitete wird zuerst ausgeführt, aber es sieht so aus, als ob die Basis zuerst ausgeführt wurde.

21
Paolo Tedesco

Wie andere gesagt haben, wird der Basiskonstruktor zuerst aufgerufen. Konstruktoren sind jedoch nicht das erste, was passiert.

Angenommen, Sie haben Klassen wie diese:

class A {}

class B : A {}

class C : B {}

Zunächst werden die Feldinitialisierer in der Reihenfolge der am häufigsten abgeleiteten Klassen bis zu den am wenigsten abgeleiteten Klassen aufgerufen. Also erst Feldinitialisierer von C, dann B, dann A.

Die Konstruktoren werden dann in umgekehrter Reihenfolge aufgerufen: Zuerst der Konstruktor von A, dann B, dann C.

6
Joel B Fant

Ich würde Base sagen

EDIT siehe:

http://www.c-sharpcorner.com/UploadFile/rajeshvs/ConsNDestructorsInCS11122005010300AM/ConsNDestructorsInCS.aspx

dort heißt es:

using System;
class Base
{

public Base()
{
    Console.WriteLine("BASE 1");
}
public Base(int x)
{
    Console.WriteLine("BASE 2");
}
}

class Derived : Base
{
public Derived():base(10)
{
    Console.WriteLine("DERIVED CLASS");
}
}

class MyClient
{
public static void Main()
{
    Derived d1 = new Derived();
}
}

Dieses Programm gibt aus

BASE2

ABGELEITETE KLASSE

4
Mastermind

Eric Lippert hatte einen interessanten Beitrag zum Thema Objektinitialisierung, der den Grund für die Bestellung von Konstruktoren und Feldinitialisierern erklärt:

Warum werden Initialisierer als Konstruktoren in umgekehrter Reihenfolge ausgeführt? Teil 1
Warum werden Initialisierer als Konstruktoren in der entgegengesetzten Reihenfolge ausgeführt? Teil 2

2
Emperor XLII

Base Constructor wird zuerst aufgerufen. Der Initialisierer von Feldern in abgeleiteten Klassen wird jedoch zuerst aufgerufen.

Die aufrufende Reihenfolge ist

  1. initialisierer für abgeleitete Klassenfelder
  2. basisklassenfeldinitialisierer
  3. basisklassenkonstruktor
  4. abgeleiteter Klassenkonstruktor

(Sie können 2 und 3 als Ganzes behandeln, um die Basisklasse zu konstruieren.)

Entnommen aus CSharp Language Speification 5.0 :

10.11.3 Konstruktorausführung

Variableninitialisierer werden in Zuweisungsanweisungen umgewandelt, und diese Zuweisungsanweisungen werden vor dem Aufruf des Instanzkonstruktors der Basisklasse ausgeführt. Diese Reihenfolge stellt sicher, dass alle Instanzfelder von ihren Variableninitialisierern initialisiert werden, bevor Anweisungen ausgeführt werden, die Zugriff auf diese Instanz haben. Gegeben das Beispiel

using System;
class A
{
    public A() {
        PrintFields();
    }
    public virtual void PrintFields() {}
}
class B: A
{
    int x = 1;
    int y;
    public B() {
        y = -1;
    }
    public override void PrintFields() {
        Console.WriteLine("x = {0}, y = {1}", x, y);
    }
}

wenn new B() zum Erstellen einer Instanz von B verwendet wird, wird die folgende Ausgabe erzeugt:

x = 1, y = 0

Der Wert von x ist 1, da der Variableninitialisierer ausgeführt wird, bevor der Instanzkonstruktor der Basisklasse aufgerufen wird. Der Wert von y ist jedoch 0 (der Standardwert von int), da die Zuweisung zu y erst ausgeführt wird, nachdem der Basisklassenkonstruktor zurückgegeben wurde. Es ist nützlich, sich Instanzvariableninitialisierer und Konstruktorinitialisierer als Anweisungen vorzustellen, die automatisch vor dem Konstruktorkörper eingefügt werden. Das Beispiel

using System;
using System.Collections;
class A
{
    int x = 1, y = -1, count;
    public A() {
        count = 0;
    }
    public A(int n) {
        count = n;
    }
}
class B: A
{
    double sqrt2 = Math.Sqrt(2.0);
    ArrayList items = new ArrayList(100);
    int max;
    public B(): this(100) {
        items.Add("default");
    }
    public B(int n): base(n – 1) {
        max = n;
    }
}

enthält mehrere variable Initialisierer; Es enthält auch Konstruktorinitialisierer für beide Formen (base und this). Das Beispiel entspricht dem folgenden Code, in dem jeder Kommentar eine automatisch eingefügte Anweisung angibt (die für die automatisch eingefügten Konstruktoraufrufe verwendete Syntax ist nicht gültig, sondern dient lediglich der Veranschaulichung des Mechanismus).

using System.Collections;
class A
{
    int x, y, count;
    public A() {
        x = 1;                                // Variable initializer
        y = -1;                               // Variable initializer
        object();                         // Invoke object() constructor
        count = 0;
    }
    public A(int n) {
        x = 1;                                // Variable initializer
        y = -1;                               // Variable initializer
        object();                         // Invoke object() constructor
        count = n;
    }
}
class B: A
{
    double sqrt2;
    ArrayList items;
    int max;
    public B(): this(100) {
        B(100);                               // Invoke B(int) constructor
        items.Add("default");
    }
    public B(int n): base(n – 1) {
        sqrt2 = Math.Sqrt(2.0);           // Variable initializer
        items = new ArrayList(100);   // Variable initializer
        A(n – 1);                         // Invoke A(int) constructor
        max = n;
    }
}
1
zwcloud
1
mmcdole

Der Exception Constructor wird aufgerufen, dann wird Ihr Child-Klassenkonstruktor aufgerufen.

Einfaches OO Prinzip

Schauen Sie hier nach http://www.dotnet-news.com/lien.aspx?ID=35151

1
CheGueVerra

Der Basiskonstruktor wird zuerst aufgerufen, andernfalls wird in Fällen, in denen Ihre "anderen Elemente" Membervariablen verwenden müssen, die von Ihrem Basiskonstruktor initialisiert wurden, ein Fehler bei der Kompilierung angezeigt, da Ihre Klassenmitglieder noch nicht initialisiert wurden.

0
kafuchau

base (?) wird aufgerufen, bevor Arbeiten im untergeordneten Konstruktor ausgeführt werden.

Dies ist auch dann der Fall, wenn Sie: base () weglassen (in diesem Fall wird der 0-Parameter-Basiskonstruktor aufgerufen).

Es funktioniert ähnlich wie Java,

public Child()
{
   super(); // this line is always the first line in a child constructor even if you don't put it there! ***
}

*** Ausnahme: Ich könnte stattdessen Super (1,2,3) einsetzen. Wenn ich aber nicht explizit einen Aufruf von super in tätige, wird super () aufgerufen.

0
Chris Cudmore

Konstruktoraufrufe werden von unten nach oben aufgerufen (ausgelöst) und von oben nach unten ausgeführt. Wenn Sie also Klasse C hatten, die von Klasse B erbt, die von Klasse A erbt, wird beim Erstellen einer Instanz von Klasse C der Konstruktor für C aufgerufen, der wiederum den Instruktor für B aufruft, der wiederum den Konstruktor für aufruft A. Nun wird der Konstruktor für A ausgeführt, dann der Konstruktor für B und dann der Konstruktor für C.

0
edirtyfour