Restringindo a acessibilidade ao acessador (Guia de Programação em C#)

As partes get e set de uma propriedade ou de um indexador são chamadas acessadores. Por padrão, esses acessadores têm a mesma visibilidade ou nível de acesso da propriedade ou do indexador aos quais pertencem. Para obter mais informações, consulte níveis de acessibilidade. No entanto, às vezes é útil restringir o acesso a um desses acessadores. Normalmente, isso envolve restringir a acessibilidade do acessador set e manter o acessador get publicamente acessível. Por exemplo:

private string _name = "Hello";

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

Neste exemplo, uma propriedade chamada Name define um acessador get e set. O acessador get recebe o nível de acessibilidade da propriedade em si, public nesse caso, embora o set acessador esteja restrito explicitamente ao aplicar o modificador de acesso get ao acessador em si.

Restrições em modificadores de acesso nos acessadores

O uso dos modificadores de acesso em propriedades ou indexadores está sujeito a estas condições:

  • Não é possível usar os modificadores de acessador em uma interface ou em uma implementação de membro de interface explícita.

  • É possível usar os modificadores de acessador somente se a propriedade ou o indexador tiver os acessadores set e get. Nesse caso, o modificador é permitido em apenas um dos dois acessadores.

  • Se a propriedade ou o indexador tiver um modificador substituir, o modificador de acessador deverá corresponder o acessador do acessador substituído, se houver.

  • O nível de acessibilidade do acessador deve ser mais restritivo do que o nível de acessibilidade na propriedade ou no indexador em si.

Modificadores de acesso em acessadores de substituição

Quando você substitui uma propriedade ou indexador, os acessadores substituídos devem estar acessíveis ao código de substituição. Além disso, a acessibilidade da propriedade/indexador, e seus acessadores, devem corresponder à propriedade/indexador substituído e seus acessadores. Por exemplo:

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

Implementando interfaces

Quando você usa um acessador para implementar uma interface, o acessador pode não ter um modificador de acesso. No entanto, se você implementar a interface usando um acessador, como get, o outro acessador poderá ter um modificador de acesso, como no exemplo a seguir:

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 { }
    }
}

Domínio de acessibilidade do acessador

Se você usar um modificador de acesso no acessador, o domínio de acessibilidade do acessador será determinado por esse modificador.

Se você não usou um modificador de acesso no acessador, o domínio de acessibilidade do acessador é determinado pelo nível de acessibilidade da propriedade ou do indexador.

Exemplo

O exemplo a seguir contém três classes, BaseClass, DerivedClass e MainClass. Há duas propriedades no BaseClass, Name e Id em ambas as classes. O exemplo demonstra como a propriedade Id no DerivedClass pode ser oculta pela propriedade Id no BaseClass quando você usa um modificador de acesso restritivo como Id ou DerivedClass. Portanto, em vez disso, quando você atribui valores a essa propriedade, a propriedade na classe BaseClass é chamada. Substituindo o modificador de acesso por público tornará a propriedade acessível.

O exemplo também demonstra que um modificador de acesso restritivo, como private ou protected, no acessador set da propriedade Name no DerivedClass impede o acesso ao acessador e gera um erro quando você atribui a ele.

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
*/

Comentários

Observe que, se você substituir a declaração new private string Id por new public string Id, você obterá a saída:

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

Name and ID in the derived class: John, John123

Confira também