2009-07-25 8 views
272

A menudo nos dicen que debemos proteger la encapsulación haciendo métodos getter y setter (propiedades en C#) para campos de clase, en lugar de exponer los campos al mundo exterior.Campos públicos frente a propiedades automáticas

Pero hay muchas ocasiones en que un campo está ahí para contener un valor y no requiere ningún cálculo para obtener o establecer. Para estos todos haríamos este número:

public class Book 
{ 
    private string _title; 

    public string Title 
    { 
      get{ return _title; } 
      set{ _title = value; } 
    } 
} 

Bueno, tengo una confesión, que no podía soportar escribir todo lo que (en realidad, fue no tener que escribirla, que fue tener que mirarlo), así que fui pícaro y utilicé campos públicos.

Luego viene lo largo de C# 3.0 y veo que añaden propiedades automáticas:

public class Book 
{ 
    public string Title {get; set;} 
} 

que es más ordenado, y estoy agradecido por ello, pero en realidad, lo que es tan diferente que sólo hacer un campo público?

public class Book 
{ 
    public string Title; 
} 
+0

posible duplicado de [Diferencia entre propiedad y campo en C# .NET 3.5+] (http://stackoverflow.com/questions/653536/difference-between-property-and-field-in-c-sharp-net- 3-5) – nawfal

+4

He convertido un feild en una propiedad solo para poder establecer un punto de interrupción en el setter –

+1

Tiendo a hacer cualquier propiedad que no sea privada porque me he dado cuenta por el camino que debo refactorizar un campo en una propiedad conducir a un dolor de cabeza innecesario. [Propiedades, campos y métodos. ¡Oh, mi!] (Http://www.codeducky.org/properties-fields-and-methods-oh-my/) menciona una incompatibilidad que me ha picado en el pasado. –

Respuesta

137

En un related question tuve hace algún tiempo, había un enlace a una publicación en el blog de Jeff, explicando algunas diferencias.

Properties vs. Public Variables

  • Reflexión funciona de forma diferente en las variables vs. propiedades, por lo que si se basan en la reflexión, es más fácil de usar todas las propiedades.
  • No se puede databind contra una variable.
  • Cambiar una variable a una propiedad es un cambio radical. Por ejemplo:

    TryGetTitle(out book.Title); // requires a variable 
    
+17

"Cambiar una variable a una propiedad es un cambio radical". Esto, por supuesto, solo se aplica al escribir una biblioteca reutilizable, que la mayoría de los desarrolladores * no * están haciendo. – Steven

+21

Además, las propiedades, incluso las propiedades automáticas, pueden ser virtuales, donde los campos no pueden. Por lo tanto, una clase base puede tener una implementación de campo de respaldo simple como la producida por el compilador para un autopropósito, mientras que las clases derivadas pueden realizar validación adicional u otra lógica/cálculos. – KeithS

+22

También un campo es una _variable_ y se puede pasar por referencia (palabra clave 'ref' o' out'), mientras que una propiedad es un par de accesadores y no se puede pasar por referencia. Por ejemplo 'bool success = TryGetMyTitle (out myBook.Title);' que usa 'out' funcionará con un campo y no funcionará con una propiedad. ¡Este es un claro ejemplo de por qué el cambio de campo a propiedad es un cambio radical! –

51

El cambio de un campo a una propiedad rompe el contrato (por ejemplo, requiere que todo el código de referencia que volver a compilar). Entonces, cuando tiene un punto de interacción con otras clases, cualquier miembro público (y generalmente protegido), desea planificar el crecimiento futuro. Hazlo usando siempre propiedades.

No hay nada que lo convierta en una propiedad de auto hoy, y 3 meses después se dará cuenta de que quiere que sea de carga lenta, y ponga un cheque nulo en el captador. Si utilizó un campo, este es un cambio de recompilación en el mejor de los casos y, en el peor, imposible, dependiendo de quién & de qué otra cosa dependa su ensamblaje.

+1

Me gustó esta respuesta porque no usa las palabras 'reflexión', 'interfaz' o 'sobrescribir'. (Lástima de "contrato") –

6

Es todo acerca de las versiones y la estabilidad de la API. No hay diferencia, en la versión 1, pero más adelante, si decide que necesita hacer de esto una propiedad con algún tipo de error al verificar en la versión 2, no tiene que cambiar su API, no hay cambios de código, en ningún otro lugar, excepto la definición de la propiedad.

64

Ignorando los problemas de la API, lo que más me parece valioso sobre el uso de una propiedad es la depuración.

El depurador CLR no admite puntos de interrupción de datos (la mayoría de los depuradores nativos lo hacen). Por lo tanto, no es posible establecer un punto de corte en la lectura o escritura de un campo en particular en una clase. Esto es muy limitante en ciertos escenarios de depuración.

Dado que las propiedades se implementan como métodos muy delgados, es posible establecer puntos de interrupción en la lectura y escritura de sus valores. Esto les da una gran ventaja sobre los campos.

0

Si luego decide comprobar que el título es único, al compararlo con una colección o una base de datos, puede hacerlo en la propiedad sin cambiar ningún código que dependa de ella.

Si solo tiene un atributo público, tendrá menos flexibilidad.

La flexibilidad adicional sin romper el contrato es lo más importante para mí sobre el uso de propiedades, y, hasta que realmente necesite la flexibilidad, la autogeneración tiene más sentido.

53

Solo porque nadie lo mencionó: No puede definir campos en Interfaces. Entonces, si tiene que implementar una interfaz específica que define propiedades, las propiedades automáticas a veces son una característica realmente agradable.

+1

Diría que si necesita una interfaz que defina propiedades, debería ser una clase abstracta. El hecho de que C# le permita definir propiedades en las interfaces, no significa que deba usarlas. Es un mal diseño. – Odys

+6

@odyodyodys - No estoy seguro de estar de acuerdo en que este es un mal diseño. Por favor explique su razonamiento? –

+3

@odyodyodys Estoy de acuerdo con zooone9243: Imp, desde el punto de vista del diseño, no hay diferencia entre declarar una propiedad y declarar un par getter/setter (que es una práctica común para las interfaces). – MartinStettner

7

No hay nada de malo en hacer un campo public. Pero recuerde crear getter/setter con private campos sin encapsulamiento. OMI, si no le importan otras características de un Property, también puede hacerlo public.

41

Una gran diferencia que a menudo se pasa por alto y no se menciona en ninguna otra respuesta: anulando. Puede declarar propiedades virtuales y anularlas, mientras que no puede hacer lo mismo para los campos de miembros públicos.

9

Otra ventaja de las propiedades implementadas automáticamente sobre los campos públicos es que puede hacer que los accesos del conjunto sean privados o protegidos, proporcionando la clase de objetos donde se definió un mejor control que el de los campos públicos.

0

Una cosa que me resulta muy útil, así como todos los motivos de código y prueba, es que si se trata de una propiedad frente a un campo, el IDE de Visual Studio muestra las referencias de una propiedad pero no de un campo.

Cuestiones relacionadas