c# - property - ¿Cuál es la mejor práctica para usar campos públicos?
propiedades en c# (11)
Creo que la mejor práctica es no hacerlo. A menos que tenga un rendimiento extremo donde necesite acceder directamente al campo, no lo haga.
Aquí hay un buen artículo al respecto:
http://csharpindepth.com/Articles/Chapter8/PropertiesMatter.aspx
Cuando escribo una clase, siempre expongo campos privados a través de una propiedad pública como esta:
private int _MyField;
public int MyField
{ get{return _MyField; }
¿Cuándo está bien exponer un campo público como este?
public int MyField;
Estoy creando una estructura llamada Resultado y mi intención es hacer esto:
public Result(bool result, string message)
{
Result = result;
Message = message;
}
public readonly int Result;
public readonly int Message;
cual es la mejor practica? ¿Alguna vez está bien hacer esto?
La mejor práctica es usar propiedades por varias razones. Primero, desacopla la API de la estructura de datos subyacente. En segundo lugar, cualquier cosa incorporada en el marco que se une a los objetos hace a las propiedades, no a los campos.
Estoy seguro de que hay más razones, pero esas dos siempre parecen ser suficientes para mí.
La respuesta que doy es que las propiedades son más amigables con Refactor.
Si tiene un ensamblaje con campos de solo lectura, cámbielos a propiedades. Si tiene otro ensamblaje que acceda a los campos (ahora propiedades), no funcionarán sin una compilación. Los campos y las propiedades no son los mismos en lo que respecta al compilador.
Volver a refactorizar, digamos que comenzó con una propiedad. Ahora necesita cambiar de dónde provienen los datos (accederá desde otra clase). Si estaba tratando con campos, tiene que tomar decisiones difíciles sobre cómo lograrlo. Las propiedades son mucho más indulgentes, porque puedes ocultar la lógica en ellas.
Me gustaría responder sobre su enfoque de solo lectura.
Readonly no es una forma de tener solo un acceso de acceso en un campo público. Utilizo principalmente readonly en un campo privado donde mi campo privado solo se puede configurar desde el constructor. Entonces, para que se entienda, un campo de solo lectura SÓLO puede establecerse en un contructor y luego solo puede acceder a él.
Las mejores prácticas es usar siempre Propiedades para acceder a sus campos después del constructor. entonces, en caso de que tuvieras que acceder a tus propiedades desde dentro de tu clase, pondría:
private readonly int result;
private readonly int message;
public Result(bool result, string message)
{
this.result = result;
this.message = message;
}
public int Result
{
get{ return result; }
private set { result = value; }
}
public int Message
{
get{ return message; }
private set { message = value; }
}
De esta forma, solo puede leer Resultado y Mensaje y todavía puede escribir desde dentro de la clase.
En caso de que use herencia, podría proteger el conjunto si es necesario.
EDITAR : Después de leer el código que hice en base a lo que se dio en la pregunta, hay algún error donde el nombre de clase Resultado probablemente arrojará un error con la propiedad Resultado y también el hecho de que estamos recibiendo un bool como resultado y una cadena como mensaje en constructor, pero tratando de enviarlos en un int esto definitivamente no funcionará. Pero lo que vale aquí es algo más lógico:
private readonly bool result;
private readonly string message;
public Answer(bool result, string message)
{
this.result = result;
this.message = message;
}
public bool Result
{
get{ return result; }
private set { result = value; }
}
public string Message
{
get{ return message; }
private set { message = value; }
}
Solo expongo campos públicos cuando son constantes (estáticas), e incluso entonces usualmente uso una propiedad.
Con "constante" me refiero a cualquier valor readonimante e inmutable, no solo uno que pueda expresarse como "const" en C #.
Incluso las variables de instancia de solo lectura (como Resultado y Mensaje) deben estar encapsuladas en una propiedad en mi vista.
Vea este artículo para más detalles.
Usar propiedades ¡Ahora es fácil que C # tenga propiedades automáticas !
En los lenguajes C-Style (como C #), debe exponer los campos a través de las propiedades. Esto también se aplica a VB.NET y otros lenguajes .NET, así como también comparten el mismo motor subyacente. La razón principal para hacer esto es que
Public MyField como Integer NO IGUALA la propiedad pública MyField como Integer, no tienen el mismo comportamiento en todas las situaciones bajo .NET.
Sin embargo, es probable que veas a muchas personas que siguen haciendo Fields públicos. Parte de esto se debe a la forma en que VB6 maneja COM. En VB6 Public MyField como Integer es equivalente a la propiedad pública MyField como Integer. Porque cuando ambos se traducen a un tipo de letra COM, ambos se implementan de la misma manera.
Esto dio lugar a muchas restricciones extrañas en VB6 sobre lo que podría ser un campo público. Restricciones que no están en .NET y en muchos otros lenguajes orientados a objetos. Estas restricciones se capturan en tiempo de compilación, por lo tanto, evitan que un programador se pegue un tiro en el pie, por así decirlo. Si tu clase era privada en VB6, algunas de estas restricciones, pero no todas, se aliviaron. La regla general era que solo podía exponer clases y tipos de datos como campos públicos.
El legado de VB6 significa que hay muchos programadores que no están conscientes de que existe una diferencia en .NET.
Debido a que .NET no nos ayuda en este aspecto, entonces debe tomar el paso tradicional de asegurarse de que todos los campos estén expuestos a través de las propiedades. De nuevo porque en .NET un campo no es lo mismo que una Propiedad.
Este artículo (señalado por otros) explica el lado .NET de él.
Recomiendo usar algo similar a esto:
public class Result{
public bool Result { get; protected set; }
public string Message { get; protected set; }
public Result(bool result, string message) {
Result = result;
Message = message;
}
}
De esta forma, no necesita declarar variables miembro, ¡deje que el compilador haga el trabajo por usted! El código es muy limpio y corto, y la refactorización es muy sencilla.
En general, si se va a utilizar un tipo como titular de datos, debe ser:
- Una estructura mutable con campos expuestos, si cada uno de los campos se comportará como un valor desde el punto de vista del tipo, y cualquier combinación arbitraria de valores de campo "tendrá sentido". Tenga en cuenta que los campos que contienen referencias a tipos de clases mutables pueden calificar si el propósito de los campos es mantener la identidad de los objetos en cuestión, en lugar de los contenidos. Las estructuras con campos mutables obtuvieron una mala reputación como resultado de los tontos compiladores de C # que interpretarían `SomeThing.SomeStruct.SomeField = whatever` como` tempStruct = SomeThing.SomeStruct; tempStruct.SomeField = whatever` sin emitir un diagnóstico, pero no hay motivo para que los programadores de hoy se preocupen por lo que harían los compiladores antiguos.
- Una clase o estructura inmutable con campos no públicos, para situaciones donde lo anterior no se aplica, y donde tener que regenerar un elemento de datos completo para cambiar un aspecto del mismo no sería demasiado molesto.
- Una clase mutable, si las referencias a ella no se mantendrán fuera de la entidad que la crea (tales referencias generalmente nunca deberían estar expuestas a código externo). Tenga en cuenta que las otras dos opciones, cuando se puede trabajar, deberían ser ampliamente preferidas, ya que una colección que utiliza un tipo de clase mutable como soporte de datos (en oposición a una colección que simplemente almacena las identidades de objetos pero no les importa lo que representan esos objetos) a menudo tendrá que hacer una copia defensiva de cualquier objeto que esté almacenado en la colección, y luego hacer una copia defensiva adicional cada vez que se lea el objeto. Las estructuras, ya sean mutables o "inmutables", deben copiarse siempre que se almacenen o se vuelvan a leer de una colección, pero dichas copias son más baratas, para cualquier estructura de tamaño , que las copias defensivas que se requerirían si se usa una clase mutable.
Si no existe una alternativa práctica al uso de una clase mutable, la cuestión de si exponer los campos públicos depende de si existe alguna necesidad previsible de que una versión de la clase incluya la lógica de validación en un conjunto de propiedades, y también si el tipo de miembro será un tipo de valor o tipo de clase. Si Bounds
es un campo público de tipo Rectangle
, una expresión como SomeClass.Bounds.Width
puede acceder al Width
del rectángulo sin tener que acceder a ningún otro miembro. Por el contrario, si Bounds
fuera una propiedad, incluso una mutable, esa expresión tendría que copiar los cuatro miembros de Bounds
en una estructura temporal, y luego acceder al campo Width
de eso.
¿Cuál es la mejor práctica para usar campos públicos?
"No". Ver también: ¿Deben prohibirse los atributos protegidos? que se refiere a los campos protegidos, pero lo que se dice que es aún más cierto para los públicos.