Share via


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 0med . 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. De kan användas som medlemsfält. När en primär konstruktorparameter används samlar kompilatorn in konstruktorparametern i ett privat fält med ett kompilatorgenererat namn. Om en primär konstruktorparameter inte används i brödtexten av typen registreras inget privat fält. Den regeln förhindrar oavsiktlig allokering av två kopior av en primär konstruktorparameter som skickas till en baskonstruktor.

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 .

Se även