Partager via


Constructeurs d’instance (guide de programmation C#)

Vous déclarez un constructeur d’instance pour spécifier le code qui est exécuté lorsque vous créez une instance d’un type avec l’expressionnew. Pour initialiser une classe statique ou des variables statiques dans une classe non statique, vous pouvez définir un constructeur statique.

Comme l’illustre l’exemple suivant, vous pouvez déclarer plusieurs constructeurs d’instances dans un type :

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

Dans l’exemple précédent, le premier constructeur sans paramètre appelle le deuxième constructeur avec les deux arguments égaux 0. Pour ce faire, utilisez le this mot clé.

Lorsque vous déclarez un constructeur d’instance dans une classe dérivée, vous pouvez appeler un constructeur d’une classe de base. Pour ce faire, utilisez le base mot clé, comme l’illustre l’exemple suivant :

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

Constructeurs sans paramètre

Si une classe n’a aucun constructeur d’instance explicite, C# fournit un constructeur sans paramètre que vous pouvez utiliser pour instancier une instance de cette classe, comme l’illustre l’exemple suivant :

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

Ce constructeur initialise les champs d’instance et les propriétés en fonction des initialiseurs correspondants. Si un champ ou une propriété n’a pas d’initialiseur, sa valeur est définie sur la valeur par défaut du type de champ ou de propriété. Si vous déclarez au moins un constructeur d’instance dans une classe, C# ne fournit pas de constructeur sans paramètre.

Un type de structure fournit toujours un constructeur sans paramètre. Le constructeur sans paramètre est soit un constructeur sans paramètre implicite qui produit la valeur par défaut d’un type ou un constructeur sans paramètre déclaré explicitement. Pour plus d’informations, consultez la section Struct initialisation et valeurs par défaut de l’article Types de structure .

Constructeurs principaux

À compter de C# 12, vous pouvez déclarer un constructeur principal dans les classes et les structs. Vous placez tous les paramètres entre parenthèses en suivant le nom de type :

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

Les paramètres d’un constructeur principal sont dans l’étendue dans le corps entier du type déclarant. Ils peuvent initialiser des propriétés ou des champs. Ils peuvent être utilisés comme variables dans des méthodes ou des fonctions locales. Ils peuvent être passés à un constructeur de base.

Un constructeur principal indique que ces paramètres sont nécessaires pour n’importe quelle instance du type. Tout constructeur écrit explicitement doit utiliser la this(...) syntaxe d’initialiseur pour appeler le constructeur principal. Cela garantit que les paramètres du constructeur principal sont définitivement attribués par tous les constructeurs. Pour tout type class, y compris les types record class, le constructeur sans paramètre implicite n'est pas émis lorsqu'un constructeur principal est présent. Pour tout type struct, y compris les types record struct, le constructeur sans paramètre implicite est toujours émis et initialise toujours tous les champs, y compris les paramètres du constructeur principal, au motif de bits nuls. Si vous écrivez un constructeur explicite sans paramètre, il doit appeler le constructeur principal. Dans ce cas, vous pouvez spécifier une valeur différente pour les paramètres du constructeur principal. Le code suivant montre des exemples de constructeurs principaux.

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

Vous pouvez ajouter des attributs à la méthode de constructeur principal synthétisée en spécifiant la method: cible sur l’attribut :

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

Si vous ne spécifiez pas la method cible, l’attribut est placé sur la classe plutôt que sur la méthode.

Dans class et struct types, les paramètres du constructeur principal sont disponibles n’importe où dans le corps du type. Le paramètre peut être implémenté en tant que champ privé capturé. Si les seules références à un paramètre sont des initialiseurs et des appels de constructeur, ce paramètre n’est pas capturé dans un champ privé. L'utilisation dans d’autres membres du type entraîne le compilateur à capturer le paramètre dans un champ privé.

Si le type inclut le record modificateur, le compilateur synthétise plutôt une propriété publique portant le même nom que le paramètre du constructeur principal. Pour record class les types, si un paramètre de constructeur principal utilise le même nom qu’un constructeur principal de base, cette propriété est une propriété publique du type de base record class . Il n’est pas dupliqué dans le type dérivé record class. Ces propriétés ne sont pas générées pour les non-typesrecord .

Voir aussi