c# - que - ¿Por qué usar miembros privados y luego usar propiedades públicas para establecerlas?
propiedades c# (5)
Visto algunos ejemplos de código donde esto sucede:
public class Foo
{
string[] m_workID;
public string[] WorkID
{
get
{
return m_workID;
}
private set
{
m_workID = value;
}
}
}
¿Cuál es el punto de esto? Desde el uso m_workID no necesario.
Además de la filosofía de encapsulación de datos orientada a objetos , le ayuda cuando necesita hacer algo cada vez que su propiedad es de lectura / escritura. Puede tener que realizar un registro, una validación o cualquier otro método de llamada más adelante en su desarrollo.
Si su propiedad es pública, tendrá que revisar todo su código para encontrarlo y modificarlo. ¿Y qué pasa si alguien usa tu código como biblioteca?
Si su propiedad es privada con los métodos de obtención / configuración apropiados, entonces cambia la obtención / configuración y eso es todo.
En general, el punto es separar la implementación (el campo) de la API (la propiedad).
Más adelante, puede, si lo desea, colocar la lógica, el registro, etc. en la propiedad sin interrumpir la compatibilidad de fuente o binaria, pero lo más importante es que está diciendo lo que su tipo está dispuesto a hacer, en lugar de cómo lo va a hacer.
Tengo un artículo que da más beneficios de usar propiedades en lugar de campos públicos.
En C # 3 puedes hacer todo esto mucho más simple con las propiedades implementadas automáticamente :
public class Foo
{
public string[] WorkID { get; private set; }
}
En ese momento, todavía tiene un captador público y un configurador privado, pero el campo de respaldo (y la implementación de la propiedad) se genera detrás de la escena. En cualquier momento, puede cambiar esto a una propiedad "normal" completamente implementada con un campo de respaldo, y aún tendrá compatibilidad binaria y de origen. (La compatibilidad de los objetos serializados es un asunto diferente, por supuesto).
Además, en este caso, no puede reflejar el comportamiento que desea (la capacidad de leer el valor públicamente pero escribirlo en privado) con un campo: puede tener un campo de solo lectura, pero solo puede escribir en él dentro del constructor. Personalmente me gustaría que hubiera una taquigrafía similar para esto:
public class Foo
{
private readonly int id;
public int Id { get { return id; } }
...
}
Como me gustan los tipos inmutables, pero eso es un asunto diferente.
En otro WorkID
diferente, generalmente no es una buena idea exponer arreglos como este de todos modos, aunque los llamadores no pueden cambiar a qué arreglo se refiere WorkID
, pueden cambiar el contenido del arreglo, que probablemente no sea lo que usted quiere.
En el ejemplo que has dado, podrías escapar sin el establecedor de propiedades, simplemente configurando el campo directamente dentro de la misma clase, pero eso significaría que si alguna vez quisieras agregar el registro, etc. tendrías que encontrar todas esas escrituras.
Muchas veces solo desea proporcionar acceso de lectura a un campo. Mediante el uso de una propiedad puede proporcionar este acceso. Como mencionó, es posible que desee realizar operaciones antes de acceder al campo (carga lenta, por ejemplo). Tiene un montón de código allí que ya no es necesario a menos que aún esté trabajando en .Net 2.0-.
Puede usar la característica de propiedades automáticas de C # 3.0 para ahorrar tiempo al escribir:
public class Foo
{
public string[] WorkID
{
get; private set;
}
}
Además, las propiedades te dan muchas ventajas en comparación con los campos:
las propiedades pueden ser virtuales
Las propiedades ocultan los detalles de la implementación (no todas las propiedades son solo accesores de variables triviales)
Las propiedades pueden contener código de validación y registro y generar eventos de cambio.
Las interfaces no pueden contener campos sino propiedades.
Una propiedad por sí misma no proporciona ningún lugar para colocar los datos: necesita el campo ( m_workID
) para el almacenamiento, pero es completamente correcto ocultar eso detrás de una propiedad por muchas, muchas razones. En C # 3.0 puede reducir esto a:
public string[] WorkID {get; private set;}
Que hará mucho de lo mismo. Tenga en cuenta que la exposición de una matriz en sí misma puede ser problemática, ya que no hay un mecanismo para proteger los datos en una matriz; al menos con una IList<string>
, podría (si fuera necesario) agregar código adicional para comprobar la integridad, o podría hacerlo inmutable. No estoy diciendo que esto deba solucionarse, pero es algo que ver.