Instanskonstruktorer (programmeringsguide för C#)
Du deklarerar en instanskonstruktor för att ange den kod som körs när du skapar en ny instans av en typ med new
uttrycket. Om du vill initiera en statisk klass eller statiska variabler i en icke-statisk klass kan du definiera en statisk konstruktor.
Som följande exempel visar kan du deklarera flera instanskonstruktorer i en typ:
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)
}
}
I föregående exempel anropar konstruktorn den första, parameterlösa, den andra konstruktorn med båda argumenten lika 0
med . Använd nyckelordet för this
att göra det.
När du deklarerar en instanskonstruktor i en härledd klass kan du anropa en konstruktor för en basklass. För att göra det använder du nyckelordet base
, som följande exempel visar:
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
}
}
Parameterlösa konstruktorer
Om en klass inte har några explicita instanskonstruktorer tillhandahåller C# en parameterlös konstruktor som du kan använda för att instansiera en instans av den klassen, som följande exempel visar:
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
}
}
Konstruktorn initierar instansfält och egenskaper enligt motsvarande initialiserare. Om ett fält eller en egenskap inte har någon initiering anges dess värde till standardvärdet för fältets eller egenskapens typ. Om du deklarerar minst en instanskonstruktor i en klass tillhandahåller C# ingen parameterlös konstruktor.
En strukturtyp tillhandahåller alltid en parameterlös konstruktor. Den parameterlösa konstruktorn är antingen en implicit parameterlös konstruktor som genererar standardvärdet för en typ eller en uttryckligen deklarerad parameterlös konstruktor. Mer information finns i avsnittet Struct-initiering och standardvärden i artikeln Strukturtyper .
Primära konstruktorer
Från och med C# 12 kan du deklarera en primär konstruktor i klasser och structs. Du placerar alla parametrar inom parenteser efter typnamnet:
public class NamedItem(string name)
{
public string Name => name;
}
Parametrarna till en primär konstruktor finns i omfånget i hela brödtexten för deklareringstypen. De kan initiera egenskaper eller fält. De kan användas som variabler i metoder eller lokala funktioner. De kan skickas till en baskonstruktor.
En primär konstruktor anger att dessa parametrar är nödvändiga för alla instanser av typen. Alla explicit skrivna konstruktorer måste använda this(...)
initieringssyntaxen för att anropa den primära konstruktorn. Det säkerställer att de primära konstruktorparametrarna definitivt tilldelas av alla konstruktorer. För alla class
typer, inklusive record class
typer, genereras inte den implicita parameterlösa konstruktorn när en primär konstruktor finns. För alla struct
typer, inklusive record struct
typer, genereras alltid den implicita parameterlösa konstruktorn och initierar alltid alla fält, inklusive primära konstruktorparametrar, till 0-bitarsmönstret. Om du skriver en explicit parameterlös konstruktor måste den anropa den primära konstruktorn. I så fall kan du ange ett annat värde för de primära konstruktorparametrarna. Följande kod visar exempel på primära konstruktorer.
// 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;
}
Du kan lägga till attribut till metoden för den syntetiserade primära konstruktorn genom att method:
ange målet för attributet:
[method: MyAttribute]
public class TaggedWidget(string name)
{
// details elided
}
Om du inte anger method
målet placeras attributet på klassen i stället för metoden.
I class
och struct
typer är primära konstruktorparametrar tillgängliga var som helst i typens brödtext. Parametern kan implementeras som ett insamlat privat fält. Om de enda referenserna till en parameter är initierare och konstruktoranrop registreras inte parametern i ett privat fält. Användning i andra medlemmar av typen gör att kompilatorn avbildar parametern i ett privat fält.
Om typen innehåller record
modifieraren syntetiserar kompilatorn i stället en offentlig egenskap med samma namn som den primära konstruktorparametern. För record class
typer, om en primär konstruktorparameter använder samma namn som en primär baskonstruktor, är den egenskapen en offentlig egenskap av bastypen record class
. Den dupliceras inte i den härledda record class
typen. Dessa egenskaper genereras inte för icke-typerrecord
.