Aller au contenu

Programmation C sharp/Propriétés et indexeurs

Un livre de Wikilivres.
Programmation C#
Programmation C#
Modifier ce modèle

Les propriétés

[modifier | modifier le wikicode]

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.

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"
}
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 | modifier le wikicode]

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 | modifier le wikicode]

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 | modifier le wikicode]

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 | modifier le wikicode]

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

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

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.

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