Utilizar propiedades (Guía de programación de C#)Using Properties (C# Programming Guide)

Las propiedades combinan aspectos de los campos y los métodos.Properties combine aspects of both fields and methods. Para el usuario de un objeto, una propiedad que parece un campo, el acceso a la propiedad necesita la misma sintaxis.To the user of an object, a property appears to be a field, accessing the property requires the same syntax. Para el implementador de una clase, una propiedad es uno o dos bloques de código que representa un descriptor de acceso get o un descriptor de acceso set.To the implementer of a class, a property is one or two code blocks, representing a get accessor and/or a set accessor. El bloque de código del descriptor de acceso get se ejecuta cuando se lee la propiedad; el bloque de código del descriptor de acceso set se ejecuta cuando se asigna un nuevo valor a la propiedad.The code block for the get accessor is executed when the property is read; the code block for the set accessor is executed when the property is assigned a new value. Una propiedad sin un descriptor de acceso set se considera de solo lectura.A property without a set accessor is considered read-only. Una propiedad sin un descriptor de acceso get se considera de solo escritura.A property without a get accessor is considered write-only. Una propiedad que tiene ambos descriptores de acceso es de lectura y escritura.A property that has both accessors is read-write.

A diferencia de los campos, las propiedades no se clasifican como variables.Unlike fields, properties are not classified as variables. Por lo tanto, no puede pasar una propiedad como un parámetro ref u out.Therefore, you cannot pass a property as a ref or out parameter.

Las propiedades tienen muchos usos: pueden validar datos antes de permitir un cambio; pueden exponer claramente datos en una clase donde esos datos se recuperan realmente de otros orígenes, como una base de datos; pueden realizar una acción cuando los datos se cambian, como generar un evento, o cambiar el valor de otros campos.Properties have many uses: they can validate data before allowing a change; they can transparently expose data on a class where that data is actually retrieved from some other source, such as a database; they can take an action when data is changed, such as raising an event, or changing the value of other fields.

Las propiedades se declaran en el bloque de clase especificando el nivel de acceso del campo, seguido del tipo de la propiedad, seguido del nombre de la propiedad y seguido de un bloque de código que declara un descriptor de acceso get o un descriptor de acceso set.Properties are declared in the class block by specifying the access level of the field, followed by the type of the property, followed by the name of the property, and followed by a code block that declares a get-accessor and/or a set accessor. Por ejemplo:For example:

public class Date
{
    private int _month = 7;  // Backing store

    public int Month
    {
        get => _month;
        set
        {
            if ((value > 0) && (value < 13))
            {
                _month = value;
            }
        }
    }
}

En este ejemplo, Month se declara como una propiedad, de manera que el descriptor de acceso set pueda estar seguro de que el valor Month se establece entre 1 y 12.In this example, Month is declared as a property so that the set accessor can make sure that the Month value is set between 1 and 12. La propiedad Month usa un campo privado para realizar un seguimiento del valor actual.The Month property uses a private field to track the actual value. A menudo, a la ubicación real de los datos de una propiedad se le conoce como la "memoria auxiliar" de la propiedad.The real location of a property's data is often referred to as the property's "backing store." Esto es común para las propiedades que usan campos privados como una memoria auxiliar.It is common for properties to use private fields as a backing store. El campo se marca como privado para asegurarse de que solo puede cambiarse llamando a la propiedad.The field is marked private in order to make sure that it can only be changed by calling the property. Para obtener más información sobre las restricciones de acceso público y privado, vea Modificadores de acceso.For more information about public and private access restrictions, see Access Modifiers.

Las propiedades implementadas automáticamente proporcionan una sintaxis simplificada para las declaraciones de propiedad simples.Auto-implemented properties provide simplified syntax for simple property declarations. Para obtener más información, vea Propiedades implementadas automáticamente.For more information, see Auto-Implemented Properties.

El descriptor de acceso getThe get Accessor

El cuerpo del descriptor de acceso get se parece al de un método.The body of the get accessor resembles that of a method. Debe devolver un valor del tipo de propiedad.It must return a value of the property type. La ejecución del descriptor de acceso get es equivalente a la lectura del valor del campo.The execution of the get accessor is equivalent to reading the value of the field. Por ejemplo, cuando se devuelve la variable privada del descriptor de acceso get y se habilitan las optimizaciones, la llamada al método de descriptor de acceso get se inserta mediante el compilador, de manera que no existe ninguna sobrecarga de llamada al método.For example, when you are returning the private variable from the get accessor and optimizations are enabled, the call to the get accessor method is inlined by the compiler so there is no method-call overhead. En cambio, un método de descriptor de acceso get virtual no puede insertarse porque el compilador no conoce en tiempo de compilación a qué método puede llamarse realmente en tiempo de ejecución.However, a virtual get accessor method cannot be inlined because the compiler does not know at compile-time which method may actually be called at run time. A continuación se muestra un descriptor de acceso get que devuelve el valor de un campo privado _name:The following is a get accessor that returns the value of a private field _name:

class Person
{
    private string _name;  // the name field
    public string Name => _name;     // the Name property            
}

Cuando hace referencia a la propiedad, excepto como el destino de una asignación, el descriptor de acceso get se invoca para leer el valor de la propiedad.When you reference the property, except as the target of an assignment, the get accessor is invoked to read the value of the property. Por ejemplo:For example:

Person person = new Person();
//...

System.Console.Write(person.Name);  // the get accessor is invoked here

El descriptor de acceso get debe finalizar en una instrucción return o throw, y el control no puede salir del cuerpo del descriptor de acceso.The get accessor must end in a return or throw statement, and control cannot flow off the accessor body.

Cambiar el estado del objeto mediante el descriptor de acceso get es un estilo de programación incorrecto.It is a bad programming style to change the state of the object by using the get accessor. Por ejemplo, el siguiente descriptor de acceso produce el efecto secundario de cambiar el estado del objeto cada vez que se tiene acceso al campo _number.For example, the following accessor produces the side effect of changing the state of the object every time that the _number field is accessed.

private int _number;
public int Number => _number++;	// Don't do this        

El descriptor de acceso get puede usarse para devolver el valor de campo o para calcularlo y devolverlo.The get accessor can be used to return the field value or to compute it and return it. Por ejemplo:For example:

class Employee
{
    private string _name;
    public string Name => _name != null ? _name : "NA"; 
}

En el segmento de código anterior, si no asigna un valor a la propiedad Name, devolverá el valor NA.In the previous code segment, if you do not assign a value to the Name property, it will return the value NA.

El descriptor de acceso setThe set Accessor

El descriptor de acceso set es similar a un método cuyo tipo de valor devuelto es void.The set accessor resembles a method whose return type is void. Usa un parámetro implícito denominado value, cuyo tipo es el tipo de la propiedad.It uses an implicit parameter called value, whose type is the type of the property. En el siguiente ejemplo, se agrega un descriptor de acceso set a la propiedad Name:In the following example, a set accessor is added to the Name property:

class Person
{
    private string _name;  // the name field
    public string Name    // the Name property
    {
        get => _name;
        set => _name = value;
    }
}

Cuando asigna un valor a la propiedad, el descriptor de acceso set se invoca mediante un argumento que proporciona el valor nuevo.When you assign a value to the property, the set accessor is invoked by using an argument that provides the new value. Por ejemplo:For example:

Person person = new Person();
person.Name = "Joe";  // the set accessor is invoked here                

System.Console.Write(person.Name);  // the get accessor is invoked here

Es un error usar el nombre de parámetro implícito, value, para una declaración de variable local en el descriptor de acceso set.It is an error to use the implicit parameter name, value, for a local variable declaration in a set accessor.

ComentariosRemarks

Las propiedades pueden marcarse como public, private, protected, internal, protected internal o private protected.Properties can be marked as public, private, protected, internal, protected internal or private protected. Estos modificadores de acceso definen cómo los usuarios de la clase pueden obtener acceso a la propiedad.These access modifiers define how users of the class can access the property. Los descriptores de acceso get y set para la misma propiedad pueden tener diferentes modificadores de acceso.The get and set accessors for the same property may have different access modifiers. Por ejemplo, get puede ser public para permitir el acceso de solo lectura desde el exterior del tipo, y set puede ser private o protected.For example, the get may be public to allow read-only access from outside the type, and the set may be private or protected. Para obtener más información, consulte Modificadores de acceso.For more information, see Access Modifiers.

Una propiedad puede declararse como una propiedad estática mediante la palabra clave static.A property may be declared as a static property by using the static keyword. Esto hace que la propiedad esté disponible para los autores de la llamada en cualquier momento, aunque no exista ninguna instancia de la clase.This makes the property available to callers at any time, even if no instance of the class exists. Para más información, vea Clases estáticas y sus miembros.For more information, see Static Classes and Static Class Members.

Una propiedad puede marcarse como una propiedad virtual mediante la palabra clave virtual.A property may be marked as a virtual property by using the virtual keyword. Esto permite que las clases derivadas invaliden el comportamiento de la propiedad mediante la palabra clave override.This enables derived classes to override the property behavior by using the override keyword. Para obtener más información sobre estas opciones, vea Herencia.For more information about these options, see Inheritance.

Una propiedad que invalida una propiedad virtual también puede sellarse, que especifica que para las clases derivadas ya no es virtual.A property overriding a virtual property can also be sealed, specifying that for derived classes it is no longer virtual. Por último, una propiedad puede declararse abstracta.Lastly, a property can be declared abstract. Esto significa que no existe ninguna implementación en la clase, y las clases derivadas deben escribir su propia implementación.This means that there is no implementation in the class, and derived classes must write their own implementation. Para obtener más información sobre estas opciones, vea Abstract and Sealed Classes and Class Members (Clases y miembros de clase abstractos y sellados [Guía de programación de C#]).For more information about these options, see Abstract and Sealed Classes and Class Members.

Nota

Es un error usar un modificador virtual, abstract u override en un descriptor de acceso de una propiedad static.It is an error to use a virtual, abstract, or override modifier on an accessor of a static property.

EjemploExample

En este ejemplo se muestran las propiedades de solo lectura, estáticas y de instancia.This example demonstrates instance, static, and read-only properties. Acepta el nombre del empleado desde el teclado, incrementa NumberOfEmployees en 1 y muestra el nombre del empleado y el número.It accepts the name of the employee from the keyboard, increments NumberOfEmployees by 1, and displays the Employee name and number.

public class Employee
{
    public static int NumberOfEmployees;
    private static int _counter;
    private string _name;

    // A read-write instance property:
    public string Name
    {
        get => _name;
        set => _name = value; 
    }

    // A read-only static property:
    public static int Counter => _counter;

    // A Constructor:
    public Employee() => _counter = ++NumberOfEmployees; // Calculate the employee's number:            
}

class TestEmployee
{
    static void Main()
    {
        Employee.NumberOfEmployees = 107;
        Employee e1 = new Employee();
        e1.Name = "Claude Vige";

        System.Console.WriteLine("Employee number: {0}", Employee.Counter);
        System.Console.WriteLine("Employee name: {0}", e1.Name);
    }
}
/* Output:
    Employee number: 108
    Employee name: Claude Vige
*/

EjemploExample

En este ejemplo se muestra cómo tener acceso a una propiedad en una clase base que está oculta mediante otra propiedad que tiene el mismo nombre en una clase derivada:This example demonstrates how to access a property in a base class that is hidden by another property that has the same name in a derived class:

public class Employee
{
    private string _name;
    public string Name
    {
        get => _name;
        set => _name = value;
    }
}

public class Manager : Employee
{
    private string _name;

    // Notice the use of the new modifier:
    public new string Name
    {
        get => _name; 
        set => _name = value + ", Manager";
    }
}

class TestHiding
{
    static void Main()
    {
        Manager m1 = new Manager();

        // Derived class property.
        m1.Name = "John";

        // Base class property.
        ((Employee)m1).Name = "Mary";

        System.Console.WriteLine("Name in the derived class is: {0}", m1.Name);
        System.Console.WriteLine("Name in the base class is: {0}", ((Employee)m1).Name);
    }
}
/* Output:
    Name in the derived class is: John, Manager
    Name in the base class is: Mary
*/

A continuación se muestran puntos importantes del ejemplo anterior:The following are important points in the previous example:

  • La propiedad Name de la clase derivada oculta la propiedad Name de la clase base.The property Name in the derived class hides the property Name in the base class. En dicho caso, el modificador new se usa en la declaración de la propiedad en la clase derivada:In such a case, the new modifier is used in the declaration of the property in the derived class:

    public new string Name
    
  • La conversión (Employee) se usa para tener acceso a la propiedad oculta de la clase base:The cast (Employee) is used to access the hidden property in the base class:

    ((Employee)m1).Name = "Mary";
    

    Para obtener más información sobre cómo ocultar miembros, vea el Modificador new.For more information about hiding members, see the new Modifier.

EjemploExample

En este ejemplo, dos clases, Cube y Square, implementan una clase abstracta, Shape, e invalidan su propiedad Area abstracta.In this example, two classes, Cube and Square, implement an abstract class, Shape, and override its abstract Area property. Tenga en cuenta el uso del modificador override en las propiedades.Note the use of the override modifier on the properties. El programa acepta el lado como una entrada y calcula las áreas del cuadrado y el cubo.The program accepts the side as an input and calculates the areas for the square and cube. También acepta el área como una entrada y calcula el lado correspondiente para el cuadrado y el cubo.It also accepts the area as an input and calculates the corresponding side for the square and cube.

abstract class Shape
{
    public abstract double Area
    {
        get;
        set;
    }
}

class Square : Shape
{
    public double side;

    //constructor
    public Square(double s) => side = s;

    public override double Area
    {
        get => side * side;
        set => side = System.Math.Sqrt(value);
    }
}

class Cube : Shape
{
    public double side;

    //constructor
    public Cube(double s) => side = s;

    public override double Area
    {
        get => 6 * side * side;                
        set => side = System.Math.Sqrt(value / 6);                
    }
}

class TestShapes
{
    static void Main()
    {
        // Input the side:
        System.Console.Write("Enter the side: ");
        double side = double.Parse(System.Console.ReadLine());

        // Compute the areas:
        Square s = new Square(side);
        Cube c = new Cube(side);

        // Display the results:
        System.Console.WriteLine("Area of the square = {0:F2}", s.Area);
        System.Console.WriteLine("Area of the cube = {0:F2}", c.Area);
        System.Console.WriteLine();

        // Input the area:
        System.Console.Write("Enter the area: ");
        double area = double.Parse(System.Console.ReadLine());

        // Compute the sides:
        s.Area = area;
        c.Area = area;

        // Display the results:
        System.Console.WriteLine("Side of the square = {0:F2}", s.side);
        System.Console.WriteLine("Side of the cube = {0:F2}", c.side);
    }
}
/* Example Output:
    Enter the side: 4
    Area of the square = 16.00
    Area of the cube = 96.00

    Enter the area: 24
    Side of the square = 4.90
    Side of the cube = 2.00
*/

Vea tambiénSee also