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
yget
. 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