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 wystąpień 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, bez parametrów, konstruktor wywołuje drugi konstruktor z obu argumentów równych 0
. W tym celu użyj słowa kluczowego this
.
Podczas deklarowania konstruktora wystąpienia 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 zapewnia 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ę Inicjowanie struktury i wartości domyślne w artykule Typy struktury.
Konstruktory podstawowe
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 podstawowego znajdują się w zakresie w całej treści typu deklaratywnego. 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 class
typu, w tym record class
typów, niejawny konstruktor bez parametrów nie jest emitowany, gdy podstawowy konstruktor jest obecny. 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 podstawowych.
// 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 class
typach i struct
podstawowe parametry konstruktora są dostępne w dowolnym miejscu w treści 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 elementach członkowskich typu powoduje, że kompilator przechwytuje 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 innychrecord
niż.