Propiedad automatizada con getter solamente, se puede configurar, ¿por qué?

95

Creé una propiedad automatizada:

public int Foo { get; } 

Esto es solo getter. Pero cuando construyo un constructor, puedo cambiar el valor:

public MyClass(string name)
{
    Foo = 5;
}

¿Por qué es posible, aunque esto sea solo para obtener?

Noam B.
fuente
En realidad, no usa un colocador (porque no tiene uno). Establece directamente el campo subyacente (que está oculto para nosotros, por lo que debe usar el nombre de la propiedad)
Dennis_E
14
¿De qué sirve una propiedad, si nunca se puede inicializar / configurar? Yacoub Massad lo ha respondido perfectamente
Vikhram

Respuestas:

122

Esta es una nueva característica de C # 6, "Propiedades automáticas de solo captador", también conocida como "Inicializadores de propiedades automáticas para propiedades de solo lectura" como se describe en este artículo de la revista MSDN 'C #: El nuevo y mejorado C # 6.0' de Mark Michaelis y en el borrador de la Especificación de lenguaje de C # 6.0 .

El establecedor del campo de solo lectura solo es accesible en el constructor, en todos los demás escenarios el campo sigue siendo de solo lectura y se comporta como antes.

Esta es una sintaxis conveniente para reducir la cantidad de código que necesita escribir y eliminar la necesidad de declarar explícitamente una variable de nivel de módulo privado para mantener el valor.

Esta característica se consideró tan importante ya que, desde la introducción de propiedades implementadas automáticamente en C # 3, las propiedades mutables (aquellas con un getter y setter) se habían vuelto más rápidas de escribir que las inmutables (aquellas con solo un getter), lo que significa que las personas eran tener la tentación de usar propiedades mutables para evitar tener que escribir el código para un campo de respaldo que generalmente se requiere para propiedades de solo lectura. Hay más información sobre las propiedades implementadas automáticamente en la sección correspondiente de la Guía de programación de Microsoft C # .

Esta publicación de blog, '# 1.207 - C # 6.0 - Inicializadores de propiedades automáticas para propiedades de solo lectura' de Sean Sexton tiene una buena explicación y un ejemplo de la siguiente manera:

Antes de C # 6.0, si deseaba una propiedad de solo lectura (inmutable), normalmente usaba un campo de respaldo de solo lectura que se inicializa en el constructor, como se muestra a continuación.

public class Dog 
{
    public string Name { get; set; }

    // DogCreationTime is immutable
    private readonly DateTime creTime;
    public DateTime DogCreationTime 
    {
        get { return creTime; }
    }

    public Dog(string name)
    {
        Name = name;
        creTime = DateTime.Now;
    }
}

En C # 6.0, puede usar propiedades implementadas automáticamente para implementar una propiedad de solo lectura. Para ello, utilice un inicializador de propiedades automáticas. El resultado es mucho más limpio que el ejemplo anterior, donde tuvimos que declarar explícitamente un campo de respaldo.

public class Dog
{
    public string Name { get; set; }

    // DogCreationTime is immutable
    public DateTime DogCreationTime { get; } = DateTime.Now;

    public Dog(string name)
    {
        Name = name;
    }
}

También se pueden encontrar más detalles en el repositorio de dotnet Roslyn en GitHub :

Las propiedades automáticas ahora se pueden declarar sin un establecedor.

El campo de respaldo de una propiedad automática de solo captador se declara implícitamente como de solo lectura (aunque esto solo importa a efectos de reflexión). Se puede inicializar a través de un inicializador en la propiedad como en el ejemplo anterior. Además, se puede asignar una propiedad de solo captador en el cuerpo del constructor del tipo declarante, lo que hace que el valor se asigne directamente al campo subyacente:

Se trata de expresar los tipos de manera más concisa, pero tenga en cuenta que también elimina una diferencia importante en el lenguaje entre los tipos mutables e inmutables: las propiedades automáticas eran una forma abreviada disponible solo si estaba dispuesto a hacer que su clase fuera mutable, y por lo tanto, la tentación de predeterminar a eso fue genial. Ahora, con propiedades automáticas exclusivas para captadores, el campo de juego se ha nivelado entre mutable e inmutable.

y en el borrador de la Especificación del lenguaje de C # 6.0 (NB: la especificación del lenguaje es definitiva en lo que respecta a Microsoft, pero aún no ha sido aprobada como estándar EMCA / ISO , de ahí el 'borrador'):

Propiedades implementadas automáticamente

Una propiedad implementada automáticamente (o autopropiedad para abreviar), es una propiedad no abstracta no externa con cuerpos de descriptores de acceso solo con punto y coma. Las propiedades automáticas deben tener un descriptor de acceso get y, opcionalmente, pueden tener un descriptor de acceso establecido.

Cuando una propiedad se especifica como una propiedad implementada automáticamente, un campo de respaldo oculto está disponible automáticamente para la propiedad y los descriptores de acceso se implementan para leer y escribir en ese campo de respaldo. Si la propiedad automática no tiene un descriptor de acceso establecido, el campo de respaldo se considera de solo lectura (campos de solo lectura). Al igual que un campo de solo lectura, también se puede asignar una propiedad automática de solo captador en el cuerpo de un constructor de la clase adjunta. Esta asignación se asigna directamente al campo de respaldo de solo lectura de la propiedad.

Una propiedad automática puede tener opcionalmente un property_initializer, que se aplica directamente al campo de respaldo como variable_initializer (inicializadores de variable).

tomRedox
fuente
1
Este es un diseño estúpido. Esto debería ser un error de tiempo de compilación si se establece en una ubicación donde la propiedad se considera de solo lectura.
Shiv
La rareza para mí es que todavía hay un error del compilador que dice CS0200 C# Property or indexer cannot be assigned to -- it is read onlycuando se usa una propiedad regular. ¿Las "propiedades automáticas de solo captador" se consideran de solo lectura o no?
Kyle Delaney
24

Esta es una nueva característica en C # 6 que le permite crear propiedades de solo lectura e inicializar sus valores desde el constructor (o en línea cuando los declare).

Si intenta cambiar el valor de esta propiedad fuera del constructor, le dará un error de compilación.

Es de solo lectura en el sentido de que una vez que inicializa su valor (en línea o dentro del constructor), no puede cambiar su valor.

Yacoub Massad
fuente
Entonces, ¿cuál es la explicación? ¿Cuál es la definición de getter?
Noam B.
16

Si no fuera posible inicializar la propiedad de solo lectura desde el constructor (o un inicializador de propiedad automática), entonces sería inútil, ya que siempre devolvería el valor predeterminado para su tipo (0 para números, nulo para tipos de referencia ). La misma semántica se aplica a los campos de solo lectura en todas las versiones de C #.

Para definir una verdadera propiedad de solo captador (que no se puede inicializar desde el constructor), debe especificar lo que devuelve como parte de la definición:

public int Foo { get { return 5; } }

O, de forma más concisa en C # 6:

public int Foo => 5;
Douglas
fuente
No es del todo cierto, las propiedades de solo lectura son muy útiles para encapsular alguna condición en su código. Puede escribir una sentencia if y casi cualquier código para evaluar otras propiedades o condiciones y devuelven un valor apropiado cada vez que se lee la propiedad
sebagomez
3
@sebagomez: No estoy seguro de entender su punto, ¿no es eso lo que demostré en mi ejemplo?
Douglas
5

"Propiedades implementadas automáticamente de solo lectura"

Antes que nada quiero aclarar que la propiedad como

public string FirstName { get; }

Se conoce como "propiedades implementadas automáticamente de solo lectura".

Para verificar esto, puede ejecutar y verificar el código anterior con Visual Studio. Si cambia la versión de idioma de C # 6.0 a C # 5.0, el compilador generará la siguiente excepción. Característica 'Propiedades implementadas automáticamente de solo lectura' no está disponible en C # 5. Utilice la versión de idioma 6 o superior.

para cambiar la versión del idioma C #, visite aquí

Ahora llego a tu segunda pregunta

“Esto es sólo getter. Pero cuando construyo un constructor, puedo cambiar el valor "

Microsoft presenta las "propiedades implementadas automáticamente de solo lectura" en la lógica de solo lectura. Como sabemos, la palabra clave "readonly" está disponible en C # 1.0. utilizamos la palabra clave "readonly" como modificador en un campo y ese campo se puede asignar de 2 formas, ya sea en el momento de la declaración o en un constructor de la misma clase.

De la misma manera, el valor de "propiedades implementadas automáticamente de solo lectura" se puede asignar de 2 maneras

Way1 (en el momento de la declaración):

public string FirstName { get; } = "Banketeshvar";

Way2 (en un constructor de la misma clase)

Person()
{
 FirstName  = "Banketeshvar";
}

Propiedad puramente de solo lectura

Si está buscando una propiedad puramente de solo lectura, elija esto

public string FullName => "Manish Sharma";

ahora no puede asignar el valor de la propiedad "FullName" del constructor. Si intenta hacerlo, arrojará las siguientes excepciones

"No se puede asignar la propiedad o el indexador 'Person.FullName'; es de solo lectura"

Banketeshvar Narayan
fuente
2
tenga en cuenta que FullName => "foo bar" se evaluará CADA VEZ.
JuFo
4

La característica de propiedad automática se agregó al lenguaje durante el lanzamiento de C # 3.0. Le permite definir una propiedad sin ningún campo de respaldo, sin embargo, aún necesita usar el constructor para inicializar estas propiedades automáticas a un valor no predeterminado. C # 6.0 introduce una nueva característica llamada inicializador automático de propiedades que le permite inicializar estas propiedades sin un constructor como el siguiente:

Anteriormente, se requiere un constructor si desea crear objetos usando una propiedad automática e inicializar una propiedad automática a un valor no predeterminado como se muestra a continuación:

public class MyClass
{
    public int Foo { get; }

    public Foo(int foo)
    {
        Foo = foo;
    }
}

Ahora, en C # 6.0, la capacidad de usar un inicializador con la propiedad automática significa que no se requiere un código de constructor explícito.

public string Foo { get; } = "SomeString";

public List<string> Genres { get; } = new List<string> { "Comedy", "Drama" };

Puedes encontrar más información sobre esto aquí.

Rahul Nikate
fuente
1

Una variable declarada readonlyse puede escribir dentro de un constructor, pero en los lenguajes que respetan el atributo, no se puede modificar después de que el constructor regrese. Ese calificador se proporcionó como una característica del lenguaje porque a menudo es necesario para campos cuyos valores variarán en función de los parámetros del constructor (lo que significa que no se pueden inicializar antes de que comience el constructor) pero no tendrán que cambiar después de que los constructores regresen, pero fue solo utilizable para variables expuestas como campos. La semántica de los readonlycampos calificados en muchos casos habría sido perfecta para los miembros públicos, excepto que a menudo es mejor para las clases exponer los miembros, incluso los inmutables, como propiedades en lugar de campos.

Así como existen propiedades automáticas de lectura-escritura para permitir que las clases expongan propiedades mutables tan fácilmente como los campos ordinarios, existen propiedades automáticas de solo lectura para permitir que las clases expongan propiedades inmutables tan fácilmente como los readonlycampos calificados. Así como los readonlycampos calificados se pueden escribir en un constructor, también ocurre con las propiedades de solo obtención.

Super gato
fuente