c# - stored - procedimientos almacenados sql ejemplos
¿Por qué las propiedades no pueden ser de solo lectura? (6)
Creo que fundamentalmente el problema es que las propiedades son simplemente azúcar sintáctica para un campo con métodos getter / setter opcionales. Las propiedades automáticas generan el campo de respaldo, por lo que requieren el "setter" o no habría forma de establecer el valor del campo de respaldo. Como las propiedades realmente se asignan a los métodos, no a los campos, no tiene sentido hacerlos de solo lectura .
Incluso si está permitido, solo podría aplicarse a las propiedades automáticas. Para las propiedades tradicionales, puede poner código arbitrario tanto en el getter como en el setter. Incluso si el setter fuera capaz de ser invocado solo en el constructor de la clase, el getter aún podría mutar el valor basado en cualquier lógica que usted decidiera poner en él. Esto sería totalmente inconsistente con el concepto de solo lectura , por lo que es necesario tener diferentes reglas de sintaxis y soporte para las propiedades automáticas / tradicionales. Dado que hay un mecanismo -utilizando propiedades tradicionales con un getter definido Y un campo de respaldo de solo lectura como en la pregunta referenciada- no veo sentido en ensuciar la sintaxis de la propiedad y posiblemente introducir confusión para algo con una implementación bastante sencilla y directa usando los constructos de lenguaje actuales.
Esta pregunta surgió en los comentarios de esta respuesta . La incapacidad de tener propiedades de solo lectura se propuso como una posible razón para usar campos en lugar de propiedades.
Por ejemplo:
class Rectangle
{
private readonly int _width;
private readonly int _height;
public Rectangle(int width, int height)
{
_width = width;
_height = height;
}
public int Width { get { return _width; } }
public int Height { get { return _height; } }
}
Pero ¿por qué no puedes hacer esto?
public int Width { get; readonly set; }
Editar (aclaración) : puede lograr esta funcionalidad en el primer ejemplo. Pero ¿por qué no puedes usar la taquigrafía de propiedad implementada automáticamente para hacer lo mismo? También sería menos desordenado, ya que no tendría que acceder directamente a los campos en su constructor; todo acceso sería a través de la propiedad.
Las propiedades pueden ser de solo lectura, simplemente no son propiedades automáticas.
Tanto el get
como el set
son necesarios para las propiedades automáticas, y no tiene sentido que una propiedad de solo lectura tenga un set
.
Puede definir una propiedad regular como propiedad de solo lectura definiendo el get
; sin embargo, incluso si el requisito para get
y set
para las propiedades automáticas no existiera, la propiedad de solo lectura no podría definirse automáticamente porque usted tiene que saber el campo de respaldo para poder establecer su valor internamente (es decir, a través del constructor).
Supongo que podría haber una plantilla / macro o algo definido en VS para generar el código, pero no podría ser una parte del lenguaje en sí.
Porque el lenguaje no lo permite
Esto puede parecer una respuesta frívola: después de todo, los diseñadores de idiomas podrían haber declarado que si readonly
de forma automática en una propiedad automática, significaría que "la propiedad es configurable pero solo en el constructor".
Pero las características no son gratis. (Eric Gunnerson lo expresa como "Cada característica comienza con menos 100 puntos "). Implementar propiedades automáticas de solo lectura hubiera requerido un esfuerzo adicional del compilador para admitir el modificador de solo lectura en una propiedad (actualmente se aplica solo a los campos), para generar el campo de respaldo apropiado y para transformar sets
de la propiedad en asignaciones al campo de respaldo. Eso es bastante trabajo para soportar algo que el usuario podría hacer razonablemente fácil al declarar un campo de respaldo de solo lectura y escribir un getter de propiedad de una sola línea, y ese trabajo tendría un costo en términos de no implementar otras características.
Entonces, muy en serio, la respuesta es que ni los diseñadores de lenguaje ni los implementadores o nunca pensaron en la idea o, más probablemente, pensaron que sería bueno tenerla, pero decidieron que había mejores lugares para gastar sus recursos limitados. No existe una restricción técnica que impida que los diseñadores e implementadores de idiomas proporcionen la característica que usted sugiere: las razones se refieren más a la economía del desarrollo de software.
Puede hacer que una propiedad automática sea de solo lectura especificando el modificador de acceso privado para establecerlo como tal
public bool Property {get; private set;}
El colocador todavía está definido, pero ya no es visible fuera de la clase donde se define la propiedad. Por otro lado, a veces es útil definir el setter como interno para que las propiedades puedan establecerse fácilmente desde el mismo ensamblado, pero no por los llamadores externos.
Si desea hacer que una propiedad sea de "solo lectura" en lo que respecta a la funcionalidad, hágalo solo suministrando el método get
, como indicó en su publicación.
public int Width { get { return _width; } }
public int Height { get { return _height; } }
El compilador incluso hará referencia a estos como "de solo lectura" si intentas escribirles.
Tener un término adicional de readonly
para una propiedad chocaría con el método set
. Parece ser una sintaxis pobre para mí, es decir, ¿cómo sabe la persona que lo lee (o el compilador) qué tiene prioridad: readonly
o set
?
Además, como se explicó en la respuesta a la que se hace referencia, readonly
aplica solo a los campos y limita la escritura en esos campos a la instanciación de la clase. Con propiedades, no puedes escribirles (no creo) ni siquiera dentro del constructor si solo tienen un método get
.
Si el propert tiene un conjunto privado, entonces es de solo lectura del mundo exterior, es decir:
string _name;
public string Name
{
get{ return _name; }
private set { _name = value; }
}
O bien, puede hacerse solo si no tiene el setter en absoluto, es decir:
string _name;
public string Name
{
get{ return _name; }
}