Accessibilité de l'accesseur asymétrique (Guide de programmation C#)

Mise à jour : novembre 2007

Les parties get et set d'une propriété ou d'un indexeur s'appellent des accesseurs. Par défaut, ces accesseurs ont la même visibilité, ou niveau d'accès : celle de la propriété ou de l'indexeur auquel ils appartiennent. Pour plus d'informations, consultez niveaux d'accessibilité. Toutefois, il peut s'avérer utile de restreindre l'accès à l'un de ces accesseurs. En général, cela implique de restreindre l'accessibilité de l'accesseur set, tout en gardant l'accesseur get publiquement accessible. Par exemple :

private string name = "Hello";

public string Name
{
    get
    {
        return name;
    }
    protected set
    {
        name = value;
    }
}

Dans cet exemple, une propriété appelée Name définit un accesseur get et set. L'accesseur get reçoit le niveau d'accessibilité de la propriété elle-même, public dans ce cas, alors que l'accesseur set est restreint explicitement par l'application du modificateur d'accès protected à l'accesseur lui-même.

Restrictions sur les modificateurs d'accès sur les accesseurs

L'utilisation des modificateurs d'accesseurs sur les propriétés ou les indexeurs est soumise aux conditions suivantes :

  • Vous ne pouvez pas utiliser de modificateurs d'accesseur sur une interface ou une implémentation de membre d'interface explicite.

  • Vous pouvez utiliser les modificateurs d'accesseur uniquement si la propriété ou l'indexeur dispose à la fois d'accesseurs set et get. Dans ce cas, le modificateur est autorisé sur uniquement un des deux accesseurs.

  • Si la propriété ou l'indexeur possède un modificateur override, le modificateur d'accesseur doit correspondre à l'accesseur de l'accesseur substitué, le cas échant.

  • Le niveau d'accessibilité sur l'accesseur doit être plus restrictif que le niveau d'accessibilité sur la propriété ou l'indexeur même.

Modificateurs d'accès sur les accesseurs de substitution

Lorsque vous substituez une propriété ou un indexeur, les accesseurs remplacés doivent être accessibles au code de substitution. Par ailleurs, le niveau d'accessibilité à la fois de la propriété et de l'indexeur, ainsi que celui des accesseurs doit correspondre à la propriété/l'indexeur et aux accesseurs substitués correspondants. Par exemple :

public class Parent
{
    public virtual int TestProperty
    {
        // Notice the accessor accessibility level.
        protected set { }

        // No access modifier is used here.
        get { return 0; }
    }
}
public class Kid : Parent
{
    public override int TestProperty
    {
        // Use the same accessibility level as in the overridden accessor.
        protected set { }

        // Cannot use access modifier here.
        get { return 0; }
    }
}

Implémentation d'interfaces

Lorsque vous utilisez un accesseur pour implémenter une interface, l'accesseur peut ne pas avoir de modificateur d'accès. Toutefois, si vous implémentez l'interface à l'aide d'un accesseur, tel que get, l'autre accesseur peut avoir un modificateur d'accès, comme dans l'exemple suivant :

public interface ISomeInterface
{
    int TestProperty
    {
        // No access modifier allowed here
        // because this is an interface.
        get;   
    }
}

public class TestClass : ISomeInterface
{
    public int TestProperty
    {
        // Cannot use access modifier here because
        // this is an interface implementation.
        get { return 10; }

        // Interface property does not have set accessor,
        // so access modifier is allowed.
        protected set { }
    }
}

Domaine d'accessibilité de l'accesseur

Si vous utilisez un modificateur d'accès sur l'accesseur, le domaine d'accessibilité de l'accesseur est déterminé par ce modificateur.

Si vous n'avez pas utilisé un modificateur d'accès sur l'accesseur, le domaine d'accessibilité de l'accesseur est déterminé par le niveau d'accessibilité de la propriété ou de l'indexeur.

Exemple

L'exemple suivant contient trois classes, BaseClass, DerivedClass et MainClass. Il y a deux propriétés sur BaseClass, Name et Id sur les deux classes. L'exemple montre comment la propriété Id sur DerivedClass peut être masquée par la propriété Id sur BaseClass lorsque vous utilisez un modificateur d'accès restrictif tel que protected ou private. Par conséquent, lorsque vous assignez des valeurs à cette propriété, la propriété sur la classe BaseClass est appelée à la place. Le remplacement du modificateur d'accès par public rend la propriété accessible.

L'exemple montre également qu'un modificateur d'accès restrictif, tel que private ou protected, sur l'accesseur set de la propriété Name dans DerivedClass empêche l'accès à l'accesseur et génère une erreur lorsque vous le lui assignez.

public class BaseClass
{
    private string name = "Name-BaseClass";
    private string id = "ID-BaseClass";

    public string Name
    {
        get { return name; }
        set { }
    }

    public string Id
    {
        get { return id; }
        set { }
    }
}

public class DerivedClass : BaseClass
{
    private string name = "Name-DerivedClass";
    private string id = "ID-DerivedClass";

    new public string Name
    {
        get
        {
            return name;
        }

        // Using "protected" would make the set accessor not accessible. 
        set
        {
            name = value;
        }
    }

    // Using private on the following property hides it in the Main Class.
    // Any assignment to the property will use Id in BaseClass.
    new private string Id
    {
        get
        {
            return id;
        }
        set
        {
            id = value;
        }
    }
}

class MainClass
{
    static void Main()
    {
        BaseClass b1 = new BaseClass();
        DerivedClass d1 = new DerivedClass();

        b1.Name = "Mary";
        d1.Name = "John";

        b1.Id = "Mary123";
        d1.Id = "John123";  // The BaseClass.Id property is called.

        System.Console.WriteLine("Base: {0}, {1}", b1.Name, b1.Id);
        System.Console.WriteLine("Derived: {0}, {1}", d1.Name, d1.Id);

        // Keep the console window open in debug mode.
        System.Console.WriteLine("Press any key to exit.");
        System.Console.ReadKey();
    }
}
/* Output:
    Base: Name-BaseClass, ID-BaseClass
    Derived: John, ID-BaseClass
*/

Commentaires

Notez que si vous remplacez la déclaration new private string Id par new public string Id, vous obtenez la sortie :

Name and ID in the base class: Name-BaseClass, ID-BaseClass

Name and ID in the derived class: John, John123

Voir aussi

Concepts

Guide de programmation C#

Référence

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

Indexeurs (Guide de programmation C#)

Modificateurs d'accès (Guide de programmation C#)