No entiendo la necesidad de tener establecedores privados que comenzaron con C # 2.
Tener un método de establecimiento para mí es permitir que el usuario establezca algunas variables en esa clase. Al hacerlo, no expondremos las variables directamente a los usuarios. En su lugar, les dejamos hacerlo a través de este método de establecimiento público.
Esto para mí está usando "encapsulación". Existen algunos argumentos que afirman que los establecedores privados le permitirán aplicar encapsulación.
¿No estoy usando la encapsulación usando métodos de establecimiento públicos? ¿Por qué necesitamos setters privados?
¿Cuál es la diferencia entre una clase inmutable y una clase con establecedores privados?
private File settingsFile = null;
y luego en uno de los constructores:if (settingsFile == null) { settingsFile = GetSettingsFile() };
. Refactorizar código como ese me hizo llorar a veces :). El hecho de que pueda establecer un miembro antes del constructor no significa que deba hacerlo, ya que, con varios constructores, esto hace que sea DIFÍCIL seguir la lógica. Los establecedores privados te obligan a establecer valores dentro del constructor o más tarde.Respuestas:
Lógicamente.
La presencia de un establecedor privado se debe a que puede usar la propiedad automática:
¿Qué harías si quieres que sea de solo lectura?
¡¡Oh mierda!! No puedo acceder a él desde mi propia clase; Debería crearlo como una propiedad normal:
Hmm ... pero perdí la función "Propiedad automática" ...
AHHH .. eso es mejor !!
fuente
Oh crap!! I can't access it from my own class
A partir de C # 6.0, esto solo es cierto fuera de la fase de inicialización. Vea mi respuesta stackoverflow.com/a/34223746/198797{get; }
NO es equivalente a{ get; private set; }
. Por la primera víaproperty.GetSetMethod(true)
regresanull
y la segundatrue
. Esto me sorprendió.Un establecedor privado es útil si tiene una propiedad de solo lectura y no desea declarar explícitamente la variable de respaldo.
Entonces:
es lo mismo que:
Para propiedades no implementadas automáticamente, le brinda una forma coherente de configurar la propiedad desde dentro su clase para que, si necesita validación, etc., solo la tenga en un lugar.
Para responder a su pregunta final, MSDN tiene esto que decir sobre los establecedores privados:
Desde la página de MSDN sobre propiedades implementadas automáticamente
fuente
Es bastante simple. Los establecedores privados le permiten crear propiedades públicas o protegidas de solo lectura.
Eso es. Ésa es la única razón.
Sí, puede crear una propiedad de solo lectura especificando solo el captador, pero con las propiedades autoimplementadas, debe especificar tanto get como set, por lo que si desea que una propiedad autoimplementada sea de solo lectura, debe usar setters privados. No hay otra forma de hacerlo.
Es cierto que los establecedores privados no se crearon específicamente para propiedades de solo lectura implementadas automáticamente, pero su uso es un poco más esotérico por otras razones, y se centra principalmente en las propiedades de solo lectura y el uso de la reflexión y la serialización.
fuente
Con la introducción de C # 6.0 y la sintaxis para inicializadores de propiedades automáticas , los definidores privados ya no son necesarios para las propiedades que solo se establecen en la inicialización, ya sea en línea o dentro del constructor.
Estas nuevas sintaxis ahora compilan:
Propiedad inicializada en línea
Propiedad inicializada del constructor
fuente
Por ejemplo, la clase de factura permite al usuario agregar o eliminar elementos de la propiedad Elementos, pero no permite que el usuario cambie la referencia Elementos (es decir, el usuario no puede asignar la propiedad Elementos a otra instancia de objeto de lista de elementos).
fuente
Digamos, por ejemplo, que no almacena la variable real a través de la propiedad ni usa el valor para calcular algo.
En tal caso, puede crear un método para hacer su cálculo
O puede hacerlo usando
En esos casos, recomendaría usar el último, ya que las propiedades refactorizan cada elemento miembro intacto.
Aparte de eso, incluso si dice que asigna la propiedad con una variable. En tal caso, dentro de su código desea escribir así:
El código anterior se ve horrible ya que el programador siempre debe tener cuidado al usar MyProperty para Get y myprop para Set.
Para mayor coherencia, puede usar un establecedor privado que hace que Propoerty sea solo de lectura en el exterior, mientras que puede usar su configurador dentro de su código.
fuente
Creo que algunas personas han bailado sobre esto, pero para mí, el valor de los establecedores privados es que puedes encapsular el comportamiento de una propiedad, incluso dentro de una clase. Como señaló abhishek, si desea disparar un evento de cambio de propiedad cada vez que cambia una propiedad, pero no desea que una propiedad se lea / escriba para el público, entonces debe usar un establecedor privado o debe aumentar el evento en cualquier lugar donde modifique el campo de respaldo. Este último es propenso a errores porque es posible que lo olvide. De manera relacionada, si la actualización de un valor de propiedad da como resultado que se realice algún cálculo o que se modifique otro campo, o una inicialización perezosa de algo, entonces también querrá resumir eso en el setter privado en lugar de tener que recordar hacerlo en todas partes. uso del campo de respaldo.
fuente
La encapsulación significa que el estado de un objeto solo ocurre a través de una interfaz definida, y debido a esto, la clase puede asegurarse de que este estado sea siempre válido y de acuerdo con el propósito de la clase.
En algunos casos, por lo tanto, está perfectamente de acuerdo con el principio de encapsulación simplemente exponer un campo públicamente: todos los valores posibles para el campo son válidos con todos los demás valores posibles de todos los demás campos y, por lo tanto, el programador puede decidir activamente permitir el campo para ser manipulado libremente por código externo.
Sin embargo, estos casos están restringidos principalmente a clases que son en su mayoría "datos antiguos sin formato". Tampoco son muy interesantes en este sentido, así que basta de ellos.
En otros casos, en otros lenguajes, se tendría un método getter y setter, algo así como
int getId()
obtener un valor yvoid setId(int val)
actualizarlo.Las propiedades nos permiten usar la misma sintaxis para leer y escribir a través de métodos que usaríamos para leer y escribir un campo. Este es un buen azúcar sintáctico, aunque no vital.
(En realidad, debido a la forma en que funciona la reflexión y casos como
DataBinder.Eval
éste, puede ser útil tener una propiedad incluso cuando un campo funcionaría bien, pero eso es otro asunto).Hasta que se introduzcan los setters privados (en realidad, lo que cambió con C # 2 es la sintaxis para tener un setter privado y un getter público o protegido en el mismo bloque), podríamos tener un método privado para hacer el trabajo del setter privado, entonces los setters privados no son realmente necesarios. Sin embargo, son útiles, por lo que aunque solo son azúcar sintáctico, son bastante útiles.
La encapsulación no es una cuestión de si sus establecedores (o captadores) son públicos, privados, protegidos o internos, sino una cuestión de si son apropiados . Comience con un valor predeterminado de que cada campo sea privado (y para el caso
readonly
) y luego, según sea necesario, agregue miembros (ya sean propiedades o métodos) que modifiquen esos campos y asegúrese de que el objeto siga siendo válido a medida que cambien . Esto asegura que se mantenga el invariante de una clase , lo que significa que las reglas que describen el conjunto válido de estados en los que puede estar nunca se rompen (los constructores también ayudan al asegurarse de que comience en un estado válido).En cuanto a su última pregunta, a ser medios inmutables que una clase no tiene público, protegido o fijadores internos y sin público, protegido o métodos internos que cambian todos los campos. Hay grados de esto, en C # hay tres grados posibles:
Todos los campos de instancia de una clase son
readonly
, por lo tanto, incluso el código privado no puede alterarlo. Se garantiza que es inmutable (cualquier cosa que intente cambiarlo no se compilará) y posiblemente se pueden realizar optimizaciones en la parte posterior de esto.Una clase es inmutable desde el exterior porque ningún miembro público cambia nada, pero el uso de no garantiza
readonly
que no se cambie desde el interior.Una clase es inmutable como se ve desde el exterior, aunque algún estado cambia como detalle de implementación. Por ejemplo, un campo podría memorizarse y, por lo tanto, mientras que desde el exterior un intento de obtenerlo simplemente recupera el mismo valor, el primer intento de este tipo realmente lo calcula y luego lo almacena para su recuperación en intentos posteriores.
fuente
Necesita un establecedor privado, si desea admitir el siguiente escenario (no solo por esto, sino que debe señalar una buena razón): Tiene una propiedad que es de solo lectura en su clase, es decir, solo la clase en sí puede cambiar , pero puede cambiarlo después de construir la instancia. Para los enlaces, necesitaría disparar un evento PropertyChanged, preferiblemente esto debería hacerse en el establecedor de propiedades (privado). En realidad, podría simplemente disparar el evento PropertyChanged desde otro lugar de la clase, pero usar el setter privado para esto es "buena ciudadanía", porque no distribuye sus activadores de cambio de propiedad en toda su clase, sino que lo mantiene en el propiedad, donde pertenece.
fuente
Sí, está utilizando la encapsulación mediante el uso de propiedades, pero la encapsulación tiene más matices que simplemente tomar el control sobre cómo se leen y escriben las propiedades. Negar que una propiedad se establezca desde fuera de la clase puede ser útil tanto para la solidez como para el rendimiento.
Una clase inmutable es una clase que no cambia una vez que se crea, por lo que se necesitan establecedores privados (o ningún establecedor) para proteger las propiedades.
Los establecedores privados se utilizaron con más frecuencia con la abreviatura de propiedad que se introdujo en C # 3. En C # 2, el establecedor a menudo se omitía y los datos privados se accedía directamente cuando se configuraban.
Esta propiedad:
es lo mismo que:
excepto que el nombre de la variable de respaldo es creado internamente por el compilador, por lo que no puede acceder directamente.
Con la propiedad abreviada, se necesita el definidor privado para crear una propiedad de solo lectura, ya que no puede acceder directamente a la variable de respaldo.
fuente
get
yset
antes de C # 2.0. Además, creo que está mezclando 2.0 y 3.0, ya que la abreviatura implementada automáticamente a la que se refiere fue 3.0.Ejemplo de caso de uso:
Tengo una instancia de un objeto de aplicación
'UserInfo'
que contiene una propiedad.SessionTokenIDV1
que no deseo exponer a los consumidores de mi clase.También necesito la capacidad de establecer ese valor de mi clase.
Mi solución fue encapsular la propiedad como se muestra y hacer que el establecedor sea privado para poder establecer el valor del token de sesión sin permitir que el código de instanciación también lo establezca (o incluso verlo en mi caso)
Editar: Etiqueta de código fija Editar: El ejemplo tenía errores que se han corregido
fuente
Créditos a https://www.dotnetperls.com/property .
los establecedores privados son los mismos que los campos de solo lectura. Solo se pueden configurar en constructor. Si intenta establecer desde fuera, obtendrá un error de tiempo de compilación.
Vea la captura de pantalla a continuación cuando intenté configurarla desde fuera de la clase.
fuente