Restriction d’accessibilité de l’accesseur (Guide de programmation C#)

Les parties get et set d’une propriété ou d’un indexeur sont appelées accesseurs. Par défaut, ces accesseurs ont la visibilité ou le niveau d’accès de la propriété ou de l’indexeur auquel ils appartiennent. Pour plus d’informations, consultez Niveaux d’accessibilité. Toutefois, il peut parfois s’avérer utile de restreindre l’accès à l’un de ces accesseurs. En général, vous restreignez 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 le cas présent, alors que l’accesseur set est restreint explicitement par l’application du modificateur d’accès protected à l’accesseur lui-même.

Notes

Les exemples de cet article n’utilisent pas de propriétés implémentées automatiquement. Les propriétés implémentées automatiquement fournissent une syntaxe concise pour déclarer des propriétés lorsqu’un champ de stockage personnalisé n’est pas requis.

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

L’utilisation de 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 sur 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é uniquement sur l’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 eux-mêmes.

Modificateurs d’accès sur les accesseurs de substitution

Quand vous substituez une propriété ou un indexeur, les accesseurs remplacés doivent être accessibles au code de substitution. Par ailleurs, l’accessibilité de la propriété/l’indexeur et de ses accesseurs doivent correspondre à la propriété/l’indexeur et à ses accesseurs substitués. 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 des interfaces

Quand 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 quand vous utilisez un modificateur d’accès restrictif tel que protected ou private. Par conséquent, quand vous affectez 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 dans la classe dérivée. Il génère une erreur lorsque vous lui donnez une affectation, ou il accède à la propriété de la classe de base du même nom, s’il est accessible.

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 suivante :

Name and ID in the base class: Name-BaseClass, ID-BaseClass Name and ID in the derived class: John, John123

Voir aussi