Freigeben über


Instanzkonstruktoren (C#-Programmierhandbuch)

Sie deklarieren einen Instanzkonstruktor, um den Code anzugeben, der beim Erstellen einer neuen Instanz eines Typs mit dem new Ausdruck ausgeführt wird. Um eine statische Klasse oder statische Variablen in einer nicht statischen Klasse zu initialisieren, können Sie einen statischen Konstruktor definieren.

Wie im folgenden Beispiel gezeigt, können Sie mehrere Instanzkonstruktoren in einem Typ deklarieren:

class Coords
{
    public Coords()
        : this(0, 0)
    {  }

    public Coords(int x, int y)
    {
        X = x;
        Y = y;
    }

    public int X { get; set; }
    public int Y { get; set; }

    public override string ToString() => $"({X},{Y})";
}

class Example
{
    static void Main()
    {
        var p1 = new Coords();
        Console.WriteLine($"Coords #1 at {p1}");
        // Output: Coords #1 at (0,0)

        var p2 = new Coords(5, 3);
        Console.WriteLine($"Coords #2 at {p2}");
        // Output: Coords #2 at (5,3)
    }
}

Im vorherigen Beispiel ruft der erste parameterlose Konstruktor den zweiten Konstruktor auf, wobei beide Argumente gleich 0 sind. Verwenden Sie dazu das this Schlüsselwort.

Wenn Sie einen Instanzkonstruktor in einer abgeleiteten Klasse deklarieren, können Sie einen Konstruktor einer Basisklasse aufrufen. Verwenden Sie dazu das base Schlüsselwort, wie das folgende Beispiel zeigt:

abstract class Shape
{
    public const double pi = Math.PI;
    protected double x, y;

    public Shape(double x, double y)
    {
        this.x = x;
        this.y = y;
    }

    public abstract double Area();
}

class Circle : Shape
{
    public Circle(double radius)
        : base(radius, 0)
    {  }

    public override double Area() => pi * x * x;
}

class Cylinder : Circle
{
    public Cylinder(double radius, double height)
        : base(radius)
    {
        y = height;
    }

    public override double Area() => (2 * base.Area()) + (2 * pi * x * y);
}

class Example
{
    static void Main()
    {
        double radius = 2.5;
        double height = 3.0;

        var ring = new Circle(radius);
        Console.WriteLine($"Area of the circle = {ring.Area():F2}");
        // Output: Area of the circle = 19.63
        
        var tube = new Cylinder(radius, height);
        Console.WriteLine($"Area of the cylinder = {tube.Area():F2}");
        // Output: Area of the cylinder = 86.39
    }
}

Parameterlose Konstruktoren

Wenn eine Klasse keine expliziten Instanzkonstruktoren aufweist, stellt C# einen parameterlosen Konstruktor bereit, mit dem Sie eine Instanz dieser Klasse instanziieren können, wie das folgende Beispiel zeigt:

public class Person
{
    public int age;
    public string name = "unknown";
}

class Example
{
    static void Main()
    {
        var person = new Person();
        Console.WriteLine($"Name: {person.name}, Age: {person.age}");
        // Output:  Name: unknown, Age: 0
    }
}

Dieser Konstruktor initialisiert Instanzfelder und Eigenschaften entsprechend den entsprechenden Initialisierern. Wenn ein Feld oder eine Eigenschaft keinen Initialisierer aufweist, wird der Wert auf den Standardwert des Felds oder des Eigenschaftentyps festgelegt. Wenn Sie mindestens einen Instanzkonstruktor in einer Klasse deklarieren, stellt C# keinen parameterlosen Konstruktor bereit.

Ein Strukturtyp stellt immer einen parameterlosen Konstruktor bereit. Der parameterlose Konstruktor ist entweder ein impliziter parameterloser Konstruktor, der den Standardwert eines Typs oder einen explizit deklarierten parameterlosen Konstruktor erzeugt. Weitere Informationen finden Sie im Abschnitt zu Strukturinitialisierung und Standardwerten des Artikels Strukturtypen.

Hauptkonstruktoren

Ab C# 12 können Sie einen primären Konstruktor in Klassen und Strukturen deklarieren. Sie platzieren alle Parameter in Klammern nach dem Typnamen:

public class NamedItem(string name)
{
    public string Name => name;
}

Die Parameter für einen primären Konstruktor befinden sich im gesamten Textkörper des deklarierenden Typs. Sie können Eigenschaften oder Felder initialisieren. Sie können als Variablen in Methoden oder lokalen Funktionen verwendet werden. Sie können an einen Basiskonstruktor übergeben werden.

Ein primärer Konstruktor gibt an, dass diese Parameter für jede Instanz des Typs erforderlich sind. Jeder explizit geschriebene Konstruktor muss die this(...) Initialisierungssyntax verwenden, um den primären Konstruktor aufzurufen. Dadurch wird sichergestellt, dass die primären Konstruktorparameter definitiv von allen Konstruktoren zugewiesen werden. Für jeden class Typ, einschließlich record class Typen, wird der implizite parameterlose Konstruktor nicht ausgegeben, wenn ein primärer Konstruktor vorhanden ist. Für jeden struct Typ, einschließlich record struct Typen, wird der implizite parameterlose Konstruktor immer ausgegeben und initialisiert immer alle Felder, einschließlich primärer Konstruktorparameter, für das 0-Bit-Muster. Wenn Sie einen expliziten parameterlosen Konstruktor schreiben, muss er den primären Konstruktor aufrufen. In diesem Fall können Sie einen anderen Wert für die primären Konstruktorparameter angeben. Der folgende Code zeigt Beispiele für primäre Konstruktoren.

// name isn't captured in Widget.
// width, height, and depth are captured as private fields
public class Widget(string name, int width, int height, int depth) : NamedItem(name)
{
    public Widget() : this("N/A", 1,1,1) {} // unnamed unit cube

    public int WidthInCM => width;
    public int HeightInCM => height;
    public int DepthInCM => depth;

    public int Volume => width * height * depth;
}

Sie können der synthetisierten primären Konstruktormethode Attribute hinzufügen, indem Sie das method: Ziel für das Attribut angeben:

[method: MyAttribute]
public class TaggedWidget(string name)
{
   // details elided
}

Wenn Sie das method Ziel nicht angeben, wird das Attribut anstelle der Methode auf der Klasse platziert.

In class- und struct-Typen sind primäre Konstruktorparameter überall im Körper des Typs verfügbar. Der Parameter kann als erfasstes privates Feld implementiert werden. Wenn die einzigen Verweise auf einen Parameter Initialisierer und Konstruktoraufrufe sind, wird dieser Parameter nicht in einem privaten Feld erfasst. Wenn der Parameter in anderen Membern des Typs verwendet wird, führt dies dazu, dass der Compiler ihn in einem privaten Feld erfasst.

Wenn der Typ den record Modifizierer enthält, synthetisiert der Compiler stattdessen eine öffentliche Eigenschaft mit demselben Namen wie der primäre Konstruktorparameter. Wenn für record class-Typen ein primärer Konstruktorparameter denselben Namen wie ein primärer Basiskonstruktor verwendet, ist diese Eigenschaft eine öffentliche Eigenschaft des Basistyps record class. Sie wird nicht im abgeleiteten record class-Typ dupliziert. Diese Eigenschaften werden nicht für Nicht-Typen record generiert.

Siehe auch