Udostępnij za pośrednictwem


Konstruktory wystąpień (przewodnik programowania w języku C#)

Zadeklarujesz konstruktor wystąpienia, aby określić kod wykonywany podczas tworzenia nowego wystąpienia typu za pomocą new wyrażenia . Aby zainicjować klasę statyczną lub zmienne statyczne w klasie niestatycznej, można zdefiniować konstruktor statyczny.

Jak pokazano w poniższym przykładzie, można zadeklarować kilka konstruktorów instancji w jednym typie.

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)
    }
}

W poprzednim przykładzie pierwszy, bezparametrowy konstruktor wywołuje drugi konstruktor z obu argumentami równymi 0. W tym celu użyj słowa kluczowego this .

Deklarując konstruktor instancji w klasie pochodnej, można wywołać konstruktor klasy bazowej. W tym celu użyj słowa kluczowego base , jak pokazano w poniższym przykładzie:

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
    }
}

Konstruktory bez parametrów

Jeśli klasa nie ma jawnych konstruktorów wystąpień, język C# udostępnia konstruktor bez parametrów, którego można użyć do utworzenia wystąpienia wystąpienia tej klasy, jak pokazano w poniższym przykładzie:

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
    }
}

Ten konstruktor inicjuje pola i właściwości wystąpienia zgodnie z odpowiednimi inicjatorami. Jeśli pole lub właściwość nie ma inicjatora, jego wartość jest ustawiona na wartość domyślną typu pola lub właściwości. Jeśli zadeklarowasz co najmniej jeden konstruktor wystąpienia w klasie, język C# nie udostępnia konstruktora bez parametrów.

Typ struktury zawsze oferuje konstruktor bez parametrów. Konstruktor bez parametrów jest niejawnym konstruktorem bez parametrów, który generuje wartość domyślną typu lub jawnie zadeklarowany konstruktor bez parametrów. Aby uzyskać więcej informacji, zobacz sekcję inicjowania struktury i wartości domyślne artykułu Typy struktury.

Konstruktory pierwotne

Począwszy od języka C# 12, można zadeklarować podstawowy konstruktor w klasach i strukturach. Wszystkie parametry są umieszczane w nawiasach po nazwie typu:

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

Parametry konstruktora głównego są dostępne w całej treści typu zadeklarowanego. Mogą inicjować właściwości lub pola. Mogą być używane jako zmienne w metodach lub funkcjach lokalnych. Można je przekazać do konstruktora podstawowego.

Podstawowy konstruktor wskazuje, że te parametry są niezbędne dla dowolnego wystąpienia typu. Każdy jawnie napisany konstruktor musi używać this(...) składni inicjatora do wywoływania konstruktora podstawowego. Zapewnia to, że podstawowe parametry konstruktora są zdecydowanie przypisane przez wszystkie konstruktory. W przypadku dowolnego typu class, w tym typów record class, niejawny konstruktor bez parametrów nie jest emitowany, jeśli istnieje konstruktor podstawowy. W przypadku dowolnego struct typu, w tym record struct typów, niejawny konstruktor bez parametrów jest zawsze emitowany i zawsze inicjuje wszystkie pola, w tym podstawowe parametry konstruktora, do wzorca 0-bitowego. Jeśli napiszesz jawny konstruktor bez parametrów, musi wywołać konstruktor podstawowy. W takim przypadku można określić inną wartość dla podstawowych parametrów konstruktora. Poniższy kod przedstawia przykłady konstruktorów głównych.

// 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;
}

Atrybuty można dodać do syntetyzowanej podstawowej metody konstruktora, określając method: element docelowy atrybutu:

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

Jeśli nie określisz method elementu docelowego, atrybut zostanie umieszczony w klasie, a nie w metodzie.

W typach class i struct podstawowe parametry konstruktora dostępne są w dowolnym miejscu w ciele typu. Parametr można zaimplementować jako przechwycone pole prywatne. Jeśli jedynymi odwołaniami do parametru są inicjatory i wywołania konstruktora, ten parametr nie jest przechwytywany w polu prywatnym. Użycie w innych członkach typu powoduje, że kompilator zachowuje parametr w polu prywatnym.

Jeśli typ zawiera record modyfikator, kompilator zamiast tego syntetyzuje właściwość publiczną o takiej samej nazwie jak podstawowy parametr konstruktora. W przypadku record class typów, jeśli podstawowy parametr konstruktora używa tej samej nazwy co podstawowy konstruktor podstawowy, ta właściwość jest publiczną właściwością typu podstawowego record class . Nie jest ona duplikowana w typie pochodnym record class . Te właściwości nie są generowane dla typów innych niż record.

Zobacz także