Konstruktory instancí (průvodce programováním v C#)

Deklarujete konstruktor instance, který určí kód, který se spustí při vytvoření nové instance typu s výrazemnew. Chcete-li inicializovat statickou třídu nebo statické proměnné v nestatické třídě, můžete definovat statický konstruktor.

Jak ukazuje následující příklad, můžete deklarovat několik konstruktorů instance v jednom typu:

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

V předchozím příkladu první, bez parametrů, konstruktor volá druhý konstruktor s oběma argumenty rovná 0. K tomu použijte this klíčové slovo.

Když deklarujete konstruktor instance v odvozené třídě, můžete volat konstruktor základní třídy. Uděláte to tak, že použijete base klíčové slovo, jak ukazuje následující příklad:

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ů

Pokud třída nemá žádné explicitní konstruktory instancí, jazyk C# poskytuje konstruktor bez parametrů, který můžete použít k vytvoření instance této třídy, jak ukazuje následující příklad:

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

Tento konstruktor inicializuje pole a vlastnosti instance podle odpovídajících inicializátorů. Pokud pole nebo vlastnost nemá žádný inicializátor, jeho hodnota je nastavena na výchozí hodnotu typu pole nebo vlastnosti. Pokud deklarujete alespoň jeden konstruktor instance ve třídě, jazyk C# neposkytuje konstruktor bez parametrů.

Typ struktury vždy poskytuje konstruktor bez parametrů. Konstruktor bez parametrů je implicitní konstruktor bez parametrů, který vytváří výchozí hodnotu typu nebo explicitně deklarovaný konstruktor bez parametrů. Další informace naleznete v části Inicializace struktury a výchozí hodnoty v článku Typy struktur.

Primární konstruktory

Počínaje jazykem C# 12 můžete deklarovat primární konstruktor ve třídách a strukturách. Všechny parametry umístíte do závorek za názvem typu:

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

Parametry primárního konstruktoru jsou v oboru v celém těle deklarujícího typu. Mohou inicializovat vlastnosti nebo pole. Lze je použít jako proměnné v metodách nebo místních funkcích. Mohou být předány do základního konstruktoru.

Primární konstruktor označuje, že tyto parametry jsou nezbytné pro jakoukoli instanci typu. Jakýkoli explicitně napsaný konstruktor musí použít this(...) syntaxi inicializátoru k vyvolání primárního konstruktoru. Tím zajistíte, že parametry primárního konstruktoru budou rozhodně přiřazeny všemi konstruktory. U jakéhokoli class typu, včetně record class typů, se implicitní konstruktor bez parametrů nevygeneruje, pokud je k dispozici primární konstruktor. U libovolného struct typu, včetně record struct typů, je implicitní konstruktor bez parametrů vždy generován a vždy inicializuje všechna pole, včetně parametrů primárního konstruktoru, na 0bitový vzor. Pokud napíšete explicitní konstruktor bez parametrů, musí vyvolat primární konstruktor. V takovém případě můžete pro parametry primárního konstruktoru zadat jinou hodnotu. Následující kód ukazuje příklady primárních konstruktorů.

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

Do syntetizované primární metody konstruktoru můžete přidat atributy zadáním method: cíle atributu:

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

Pokud cílovou hodnotu nezadáte method , atribut se umístí do třídy místo metody.

Parametry class primárního konstruktoru jsou struct k dispozici kdekoli v těle typu. Dají se použít jako pole členů. Při použití primárního parametru konstruktoru kompilátor zachytí parametr konstruktoru v privátním poli s názvem vygenerovaným kompilátorem. Pokud se v těle typu nepoužívá parametr primárního konstruktoru, nezachytí se žádné soukromé pole. Toto pravidlo zabraňuje náhodnému přidělení dvou kopií parametru primárního konstruktoru, který je předán do základního konstruktoru.

Pokud typ obsahuje record modifikátor, kompilátor místo toho syntetizuje veřejnou vlastnost se stejným názvem jako primární konstruktor parametr. U record class typů platí, že pokud parametr primárního konstruktoru používá stejný název jako základní primární konstruktor, je tato vlastnost veřejnou vlastností základního record class typu. Není duplicitní v odvozeném record class typu. Tyto vlastnosti nejsou generovány pro jinérecord typy.

Viz také