2009-04-10 20 views
14

Otro ser capaz de valores de control de cordura en un colocador ¿hay una razón más subyacente para preferir las propiedades a las variables públicas?¿Por qué prefieren Propiedades a variables públicas?

+0

Efectivamente un engañado de http://stackoverflow.com/questions/641619/when-should-you-use-a-field-rather-than-a-property y http://stackoverflow.com/questions/379041/what-is-the-best-practice-for-use-public-fields/379057 - entre otros. – tvanfosson

Respuesta

22

Hemos tenido este tema antes, pero no puedo encontrar nada ahora.

En resumen: sus necesidades podrían cambiar: donde ahora no hay una verificación de cordura, se podría requerir una en el futuro. Sin embargo, si cambia sus campos públicos por propiedades, esto rompe la compatibilidad binaria: todos los clientes que usan su código/biblioteca tendrían que volver a compilar.

Esto es malo porque puede costar mucho dinero.

El uso de propiedades desde el principio evita este problema. Esto incluso cuenta para el código que no es parte de una biblioteca. ¿Por qué? Porque nunca se sabe: el código (¡incluso si es altamente específico del dominio!) Puede resultar útil, por lo que desea refactorizarlo en una biblioteca. Obviamente, este proceso de refactorización es mucho más fácil si ya está usando propiedades en lugar de campos públicos/protegidos.

Además, escribiendo propiedades públicas es fácil en C# 3.0, ya que sólo puede utilizar las propiedades de auto-aplicado, que le ahorra un poco de código:

public DataType MyProperty { get; set; } 

implementará el campo respaldo necesario y captador/definidor código para ti

Agregaré una nota personal: el comportamiento de .NET en este sentido es un poco vago. El compilador podría simplemente cambiar los campos públicos por propiedades sobre la marcha, evitando así el problema. VB6 ya hizo esto para clases expuestas a COM y no veo ninguna razón para que VB.NET y C# no hagan lo mismo. Quizás alguien en los equipos de compilación (¿Jared?) Podría comentar sobre esto.

+1

Ignorando la pregunta debería, hay muchas razones por las cuales el compilador no puede hacer esto. Hay 2 razones que vienen inmediatamente a la mente. 1) nombres y 2) llamar a una propiedad no es lo mismo que acceder a un campo (rendimiento, ref y fuera). Desafortunadamente no hay suficiente espacio aquí para comentar realmente – JaredPar

+2

(cont) y el hilo está cerrado. Pero la versión corta es que el usuario está pidiendo un artículo y le está dando un reemplazo no igual. Los usuarios a menudo no están contentos cuando haces eso. – JaredPar

+0

Gracias por la respuesta, Jared. :-) –

3

Jeff Atwood has blogged about it:

Hay razones válidas para hacer una propiedad trivial, tal y como se ha representado anteriormente:

  • 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.
  • Al cambiar una variable a una propiedad es a breaking change.

Es una pena hay fricción tanto de sentido entre variables y propiedades; la mayoría de las veces hacen exactamente lo mismo. Kevin Dente propusieron un poco de nueva sintaxis que nos daría lo mejor de ambos mundos:

public property int Name; 

Sin embargo, si la diferencia entre la variable y la propiedad es un problema tan continuo, me pregunto si una solución más radical está en orden. ¿No podríamos eliminar las variables completamente a favor de las propiedades? ¿Las propiedades no hacen exactamente lo mismo que las variables, pero con un mejor control granular de la visibilidad?

0

El uso de propiedades hace que el código esté más orientado a objetos. Al hacer públicas las variables miembro, está exponiendo su implementación.

también ver este link de Guía de programación de C# 's

3

Cambio de un campo a una propiedad en el futuro se considera un cambio romper. Los campos se consideran detalles de implementación de las clases y los expone públicamente rompe la encapsulación.

+0

Es solo un cambio si el código de llamada no se puede volver a compilar, la mayoría de las veces es el propietario del código de la persona que llama y lo compila el mismo sistema de compilación. Por lo tanto, esto no es un problema para la mayoría de las personas del equipo .NET framework. –

+0

@Ian Ringrose: tampoco es completamente compatible con la fuente. Por ejemplo, su código podría hacer un 'ref obj.MyField'. No puede cambiar 'MyField' a' MyProperty' sin cambiar la fuente. –

+0

@Ian: Es un cambio radical - http://msdn.microsoft.com/en-us/library/ms182141(VS.80).aspx – Cerebrus

2

Si trabaja en un entorno cerrado - usted no desarrollar un SDK, todas las clases se utilizan dentro de un mismo marco del proyecto - no hay diferencia.

El argumento habitual es que "en el futuro es posible que tenga que hacer algún tipo de control sobre los valores, por lo que es más fácil con propiedades". No lo compro en absoluto.

El uso de campos públicos es más fácil de leer, menos decoración y más fácil de usar.

+0

"¿Más fácil de usar?" ¿Cómo es posible? –

0

Sí.

Considérese una varibale pública que ahora contiene una cadena, sólo tiene que configurarlo. Sin embargo, si decide que esa variable pública debe contener un objeto que debe inicializarse con una cadena, deberá cambiar todo el código con su objeto original. Pero si hubiera usado setter, solo tendría que cambiar el setter para inicializar el objeto con la cadena proporcionada.

1

También puede proteger el acceso de escritura y permitir el acceso de lectura con una propiedad:

public int Version { get; private set; } 
+0

Esto en realidad no se compila. Creo que lo que quieres decir es: 'public int Version {get; conjunto privado; } ' –

7

En pocas palabras:

  • Puede controlar acceso (sólo lectura,
    writeonly, lectura/escritura)
  • puede validar los valores de la hora de establecer una propiedad (comprobar NULL etc)
  • puede realizar un procesamiento adicional, tales como la inicialización perezosa
  • Puede cambiar el implementación subyacente. Por ejemplo, una propiedad puede estar respaldada por un miembro de variable de ahora, pero se puede cambiar a estar respaldada por una fila DB sin romper cualquier código de usuario.
Cuestiones relacionadas