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

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

private string _name = "Hello";

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

Neste exemplo, uma propriedade chamada Name define um get e set accessor. O get acessador recebe o nível de acessibilidade da própria propriedade, public neste caso, enquanto o set acessador é explicitamente restrito pela aplicação do modificador de acesso protegido ao próprio acessador.

Nota

Os exemplos neste artigo não usam propriedades implementadas automaticamente. As propriedades implementadas automaticamente fornecem uma sintaxe concisa para declarar propriedades quando um campo de suporte personalizado não é necessário.

Restrições sobre modificadores de acesso em acessadores

O uso dos modificadores de acesso em propriedades ou indexadores está sujeito às seguintes condições:

  • Não é possível usar modificadores de acesso em uma interface ou em uma implementação explícita de membro da interface .
  • Você pode usar modificadores de acessador somente se a propriedade ou indexador tiver ambos e set get acessadores. Neste caso, o modificador é permitido em apenas um dos dois acessórios.
  • Se a propriedade ou indexador tiver um modificador de substituição , o modificador de acessador deverá corresponder ao acessador do acessador substituído, se houver.
  • O nível de acessibilidade no acessador deve ser mais restritivo do que o nível de acessibilidade na própria propriedade ou indexador.

Modificadores de acesso na substituição de acessadores

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 deve corresponder à propriedade/indexador substituída correspondente 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; }
    }
}

Implementação de 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 pode 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 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 em DerivedClass pode ser ocultada pela propriedade Id quando BaseClass você usa um modificador de acesso restritivo, como protegido ou privado. Portanto, quando você atribui valores a essa propriedade, a propriedade na BaseClass classe é chamada em vez disso. A substituição do 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 , no set acessador da Name propriedade em DerivedClass impede o acesso ao acessador na protectedclasse derivada. Ele gera um erro quando você atribui a ele, ou acessa a propriedade de classe base do mesmo nome, se estiver acessível.

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, obterá a saída:

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

Consulte também