Propriétés (Guide de programmation C#)

Une propriété est un membre qui fournit un mécanisme flexible pour la lecture, l'écriture ou le calcul de la valeur d'un champ privé. Les propriétés peuvent être utilisées comme s’il s’agissait de membres de données publics, mais ce sont en fait des méthodes spéciales appelées accesseurs. Cette fonction permet aux données d’être facilement accessibles tout en aidant à promouvoir la sécurité et la flexibilité des méthodes.

Vue d’ensemble des propriétés

  • Les propriétés permettent à une classe d'exposer un moyen public d'obtenir et de définir des valeurs, tout en masquant le code d'implémentation ou de vérification.
  • Un accesseur de propriété get est utilisé pour retourner la valeur de la propriété et un accesseur de propriété set est utilisé pour affecter une nouvelle valeur. Un accesseur de propriété init est utilisé pour attribuer une nouvelle valeur uniquement pendant la construction d’objet. Ces accesseurs peuvent avoir différents niveaux d’accès. Pour plus d’informations, consultez Restriction d’accessibilité de l’accesseur.
  • Le mot-clé valeur est utilisé pour définir la valeur le set ou init assignée par l'accesseur.
  • Les propriétés peuvent être en lecture-écriture (elles ont un accesseur get et un accesseur set), en lecture seule (elles ont un accesseur get, mais pas d’accesseur set) ou en écriture seule (elles ont un accesseur set, mais pas d’accesseur get). Les propriétés en écriture seule sont rares et sont généralement utilisées pour restreindre l’accès aux données sensibles.
  • Les propriétés simples qui ne nécessitent pas de code d’accesseur personnalisé peuvent être implémentées en tant que définitions de corps d’expression ou en tant que propriétés implémentées automatiquement.

Propriétés avec des champs de stockage

Un modèle de base pour l’implémentation d’une propriété consiste à utiliser un champ de stockage privé pour définir et extraire la valeur de propriété. L’accesseur get retourne la valeur du champ privé et l’accesseur set peut effectuer une validation des données avant d’assigner une valeur au champ privé. Les deux accesseurs peuvent également effectuer des opérations de conversion ou de calcul sur les données avant de stocker ou retourner les données.

L’exemple suivant illustre ce modèle. Dans cet exemple, la classe TimePeriod représente un intervalle de temps. La classe stocke l’intervalle de temps en secondes, en interne, dans un champ privé nommé _seconds. L’utilisateur peut éventuellement spécifier l’intervalle de temps en heures à l’aide de la propriété en lecture-écriture Hours. Les deux accesseurs de propriété get et set effectuent ensuite la conversion nécessaire des heures en secondes. De plus, l’accesseur set valide les données et lève une exception ArgumentOutOfRangeException si le nombre d’heures n’est pas valide.

public class TimePeriod
{
    private double _seconds;

    public double Hours
    {
        get { return _seconds / 3600; }
        set
        {
            if (value < 0 || value > 24)
                throw new ArgumentOutOfRangeException(nameof(value),
                      "The valid range is between 0 and 24.");

            _seconds = value * 3600;
        }
    }
}

Vous pouvez accéder aux propriétés pour obtenir et définir la valeur, comme illustré dans l’exemple suivant :

TimePeriod t = new TimePeriod();
// The property assignment causes the 'set' accessor to be called.
t.Hours = 24;

// Retrieving the property causes the 'get' accessor to be called.
Console.WriteLine($"Time in hours: {t.Hours}");
// The example displays the following output:
//    Time in hours: 24

Définitions de corps d’expression

Les accesseurs de propriété sont souvent des instructions sur une ligne qui ne font qu’assigner ou retourner le résultat d’une expression. Vous pouvez implémenter ces propriétés en tant que membres expression-bodied. Les définitions de corps d’expression se composent du symbole => suivi de l’expression à assigner à la propriété ou à récupérer de la propriété.

Les propriétés en lecture seule peuvent implémenter l’accesseur get en tant que membre expression-bodied. Dans ce cas, le mot clé d’accesseur get et le mot clé return ne sont pas utilisés. L’exemple suivant implémente la propriété en lecture seule Name en tant que membre expression-bodied.

public class Person
{
    private string _firstName;
    private string _lastName;

    public Person(string first, string last)
    {
        _firstName = first;
        _lastName = last;
    }

    public string Name => $"{_firstName} {_lastName}";
}

Les accesseurs get et set peuvent être implémentés en tant que membres expression-bodied. Dans ce cas, les mots clés get et set doivent être spécifiés. L’exemple suivant illustre l’utilisation de définitions de corps d’expression pour les deux accesseurs. Le mot clé return n’est pas utilisé avec l’accesseur get.

public class SaleItem
{
    string _name;
    decimal _cost;

    public SaleItem(string name, decimal cost)
    {
        _name = name;
        _cost = cost;
    }

    public string Name
    {
        get => _name;
        set => _name = value;
    }

    public decimal Price
    {
        get => _cost;
        set => _cost = value;
    }
}

Propriétés implémentées automatiquement

Dans certains cas, les accesseurs de propriété get et set ne font qu’assigner une valeur à un champ de stockage, ou récupérer une valeur d’un champ de stockage, sans inclure de logique supplémentaire. En utilisant des propriétés implémentées automatiquement, vous simplifiez votre code, tout en laissant le compilateur C# fournir le champ de stockage de manière transparente.

Si une propriété a à la fois un accesseur get et un accesseur set (ou get et init), les deux doivent être implémentés automatiquement. Vous définissez une propriété implémentée automatiquement à l’aide des mots clés get et set sans fournir d’implémentation. L’exemple suivant est identique à l’exemple précédent, sauf qu’il utilise les propriétés implémentées automatiquement Name et Price. L’exemple supprime également le constructeur paramétrable afin que les objets SaleItem soient désormais initialisés avec un appel au constructeur sans paramètre et à un initialiseur d’objet.

public class SaleItem
{
    public string Name
    { get; set; }

    public decimal Price
    { get; set; }
}

Les propriétés implémentées automatiquement peuvent déclarer différentes accessibilités pour les accesseurs get et set. Vous déclarez généralement un accesseur get public et un accesseur set privé. Pour en savoir plus, consultez l’article sur la restriction de l’accessibilité de l’accesseur.

Propriétés requises

À partir de C# 11, vous pouvez ajouter le membre required pour forcer le code client à initialiser une propriété ou un champ :

public class SaleItem
{
    public required string Name
    { get; set; }

    public required decimal Price
    { get; set; }
}

Pour créer un SaleItem, vous devez définir les propriétés Name et Price à l’aide d’initialiseurs d’objet, comme indiqué dans le code suivant :

var item = new SaleItem { Name = "Shoes", Price = 19.95m };
Console.WriteLine($"{item.Name}: sells for {item.Price:C2}");

Spécification du langage C#

Pour plus d’informations, consultez Propriétés dans la spécification du langage C#. La spécification du langage est la source de référence pour la syntaxe C# et son utilisation.

Voir aussi