Restringir la accesibilidad del descriptor de acceso (Guía de programación de C#)

Las partes get y set de una propiedad o un indexador se denominan descriptores de acceso. De forma predeterminada, estos descriptores de acceso tienen la misma visibilidad o nivel de acceso de la propiedad o el indexador al que pertenecen. Para obtener más información, vea Niveles de accesibilidad. En cambio, a veces resulta útil restringir el acceso a uno de estos descriptores de acceso. Normalmente, restringe la accesibilidad del descriptor de acceso set, mientras que se mantiene el descriptor de acceso get accesible públicamente. Por ejemplo:

private string _name = "Hello";

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

En este ejemplo, una propiedad denominada Name define un descriptor de acceso get y set. El descriptor de acceso get recibe el nivel de accesibilidad de la propiedad, public en este caso, mientras que el descriptor de acceso set se restringe explícitamente al aplicar el modificador de acceso protected al propio descriptor de acceso.

Nota

Los ejemplos de este artículo no usan propiedades implementadas automáticamente. Las propiedades implementadas automáticamente proporcionan una sintaxis concisa para declarar propiedades cuando no se requiere un campo de respaldo personalizado.

Restricciones en los modificadores de acceso en descriptores de acceso

Usar los modificadores de descriptor de acceso en propiedades o indexadores está sujeto a estas condiciones:

  • No puede usar los modificadores de descriptor de acceso en una interfaz o en una implementación explícita del miembro interface.
  • Puede usar modificadores de descriptor de acceso solo si la propiedad o el indexador tienen los descriptores de acceso set y get. En este caso, se permite el modificador solo en uno de los dos descriptores de acceso.
  • Si la propiedad o el indexador tienen un modificador override, el modificador de descriptor de acceso debe coincidir con el descriptor de acceso del descriptor de acceso invalidado, si lo hay.
  • El nivel de accesibilidad del descriptor de acceso debe ser más restrictivo que el nivel de accesibilidad de la propiedad o el indexador.

Modificadores de acceso en descriptores de acceso de invalidación

Al invalidar una propiedad o un indexador, los descriptores de acceso invalidados deben ser accesibles para el código de invalidación. Además, la accesibilidad de la propiedad y el indexador y sus descriptores de acceso debe coincidir con la propiedad y el indexador invalidados correspondientes y sus descriptores de acceso. Por ejemplo:

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

Implementar interfaces

Al usar un descriptor de acceso para implementar una interfaz, este no puede tener un modificador de acceso. En cambio, si implementa la interfaz con un descriptor de acceso, como get, el otro descriptor de acceso puede tener un modificador de acceso, como en el ejemplo siguiente:

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

Dominio de accesibilidad de descriptor de acceso

Si usa un modificador de acceso en el descriptor de acceso, el dominio de accesibilidad del descriptor de acceso viene determinado por este modificador.

Si no ha usado un modificador de acceso en el descriptor de acceso, el dominio de accesibilidad del descriptor de acceso viene determinado por el nivel de accesibilidad de la propiedad o el indexador.

Ejemplo

En el ejemplo siguiente, se incluyen tres clases: BaseClass, DerivedClass y MainClass. Hay dos propiedades en BaseClass, Name y Id en ambas clases. En el ejemplo, se muestra cómo la propiedad Id en DerivedClass se puede ocultar con la propiedad Id en BaseClass al usar un modificador de acceso restrictivo como protected o private. Por tanto, cuando asigna valores a esta propiedad, se llama en su lugar a la propiedad en la clase BaseClass. Si se reemplaza el modificador de acceso por public, la propiedad será accesible.

En el ejemplo, también se muestra que un modificador de acceso restrictivo, como private o protected, en el descriptor de acceso set de la propiedad Name en DerivedClass impide el acceso al descriptor de acceso en la clase derivada. Genera un error al asignarlo o accede a la propiedad de clase base del mismo nombre, si es accesible.

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

Comentarios

Tenga en cuenta que, si reemplaza la declaración new private string Id por new public string Id, obtendrá el resultado:

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

Vea también