Programmation C sharp/Propriétés et indexeurs

Programmation C#
Programmation C#
Modifier ce modèle

Les propriétés

modifier

Une propriété est une valeur qui peut être lue ou modifiée, comme une variable. Ces deux opérations sont en fait réalisées par les accesseurs get et set. Si l'un de ces deux accesseurs est manquant, la propriété sera alors soit en lecture seule, soit en écriture seule.

Syntaxe

modifier
Type Nom_de_la_propriété
{
    get // propriété lue
    {
        code retournant une valeur du Type spécifié
    }
    set // propriété modifiée
    {
        code utilisant le paramètre prédéfini "value"
    }
}

Le code contenu dans chaque bloc est le même que celui que l'on placerait pour implémenter les méthodes suivantes :

Type getNom_de_la_propriété()
{
    code retournant une valeur du Type spécifié
}
void setNom_de_la_propriété(Type value) // propriété modifiée
{
    code utilisant le paramètre prédéfini "value"
}

Exemple

modifier
private string _message;
public string Message
{
    get
    {
        return _message;
    }
    set
    {
        _message = value;
    }
}

Utilisation :

Message = "Test de la propriété" ; // <- accesseur set
Console.WriteLine( Message ); // <- accesseur get
Message += " et message ajouté"; // <- accesseurs get et set

Noms réservés

modifier

Depuis la version 2003 du compilateur, lorsqu'une propriété est créée, deux noms de méthodes sont réservés pour les deux accesseurs :

  • type get_Nom_propriété()
  • void set_Nom_propriété(type value)

La classe ne peut donc avoir de méthodes portant l'une de ces deux signatures.

Accesseurs simplifiés

modifier

Une propriété en lecture seule possède un accesseur de lecture get mais aucun accesseur d'écriture set, comme dans l'exemple suivant :

private string _message;
public string MessageSize
{
    get
    {
        return _message.Length();
    }
}

Depuis C#6.0 il est possible de simplifier la définition d'une telle propriété : le nom de la propriété est directement associé à l'expression retournée par l'accesseur de lecture en utilisant l'opérateur =>.

private string _message;
public string MessageSize => _message.Length();

Depuis C#7.0 il est possible d'utiliser cette syntaxe sur les accesseurs, qui est donc applicable également à une propriété en lecture et écriture, comme illustré par cet exemple :

private string _message;
public string Message
{
    get => _message;
    set => _message = value;
}

Accesseurs auto-implémentés

modifier

Une propriété peut également avoir des accesseurs auto-implémentées :

  • La variable de stockage de la valeur n'a plus à être déclarée : elle est générée par le compilateur ;
  • Dès que l'un des accesseurs est auto-implémenté, les autres doivent l'être également.

Exemple :

public class Test
{
    public string Message { get; set; }
}

La classe n'ayant aucun constructeur explicite, l'initialisation d'un objet peut se faire en utilisant la syntaxe suivante permettant d'initialiser les propriétés :

Test test1 = new Test{ Message="Exemple de test"; };
test1.Message = "Autre test";

Accesseurs d'initialisation

modifier

Selon les accesseurs définis pour une propriété :

  • Celle ci est en lecture seule si seulement l'accesseur get est défini,
  • Ou en lecture-écriture quand les deux accesseurs get et set sont définis.

Depuis C#9.0, il existe un cas intermédiaire permettant de définir une propriété qui devient en lecture seule après initialisation de l'objet, en déclarant un accesseur nommé init.

Exemple :

public class Test
{
    public string Message { get; init; }
}

L'accesseur init est utilisé lors de l'initialisation de l'objet.

Test test1 = new Test{ Message="Exemple de test"; }; // <-- OK, appelle l'accesseur init
test1.Message = "Autre test"; // <-- ERREUR, pas d'accesseur set

Quand l'accesseur init est implémenté, il peut servir à initialiser des champs readonly de l'objet :

public class Test
{
    private readonly string message;
    public string Message
    {
         get => message;
         init => message = (value ?? throw new ArgumentNullException(nameof(Message)));
    }
    public string MessageSize
    {
         get => message.Length();
    }
}

Les indexeurs

modifier

Un indexeur est une propriété spéciale qui permet d'utiliser une instance de la classe comme un tableau, en utilisant les crochets.

Syntaxe

modifier
Type_élément this[ Type_index index ]
{
    get // élément [index] lu
    {
        Code retournant une valeur du Type_éléments spécifié
        dont l'index est dans le paramètre index
    }
    set // élément [index] modifié
    {
        Code utilisant le paramètre prédéfini "value"
        pour le stocker à l'index spécifié par le paramètre index
    }
}
Type_élément
Type de chaque élément du tableau virtuel.
Type_index
Type de l'indice spécifié entre crochets.
index
Variable contenant la valeur de l'indice de l'élément lu ou modifié.

L'index peut avoir un autre type que int. C'est le cas des tables de hashage de l'espace de nom System.Collections.

Exemple

modifier
public class TableauVirtuel
{
    public string this[int index] 
    {
        // lecture seule car pas d'accesseur set
        get
        {
            return "Elément"+index.ToString();
        }
    }
}
...
TableauVirtuel tab=new TableauVirtuel();
Console.WriteLine("tab[15] = " + tab[15] );
// affiche Elément15