2008-08-12 27 views
137

Nota: Esto fue publicado cuando comencé C#. Con el conocimiento de 2014, puedo decir que las propiedades automotrices se encuentran entre las mejores cosas que le han pasado al lenguaje C#.C# 3.0 auto-propiedades - ¿Útil o no?

estoy acostumbrado a crear mis propiedades en C# usando un privado y un campo público:

private string title; 
public string Title 
{ 
    get { return title; } 
    set { title = value; } 
} 

Ahora, con .NET 3.0, tenemos auto-propiedades:

public string Title { get; set; } 

que sé esto es más una pregunta filosófica/subjetiva, pero ¿hay alguna razón para usar estas propiedades automáticas, excepto de guardar cinco líneas de código para cada campo? Mi queja personal es que esas propiedades me ocultan cosas, y no soy un gran admirador de la magia negra.

De hecho, el campo privado oculto ni siquiera aparece en el depurador, lo que está bien dado el hecho de que las funciones get/set no hacen nada. Pero cuando realmente quiero implementar alguna lógica getter/setter, tengo que usar el par privado/público de todos modos.

Veo la ventaja de que guardo una gran cantidad de código (una frente a seis líneas) sin perder la capacidad de cambiar la lógica getter/setter más tarde, pero de nuevo ya puedo hacerlo simplemente declarando un campo público "Public string Título "sin la necesidad de {get; conjunto; } bloquear, incluso guardando más código.

Entonces, ¿qué es lo que me falta aquí? ¿Por qué alguien realmente querría usar auto-propiedades?

+76

"Mi queja personal es que esas propiedades me ocultan cosas y no soy un gran admirador de la magia negra". ¿Huh? TÚ ERES consciente de que el compilador te oculta una tonelada todo el tiempo, ¿verdad? A menos que esté escribiendo ensamblaje (o más exactamente, los 1 y 0 reales para su código), TODO lo que escribe le oculta cosas. –

Respuesta

101

las usamos todo el tiempo de desbordamiento de pila.

Puede que también esté interesado en un debate sobre Properties vs. Public Variables. En mi humilde opinión, eso es realmente a lo que es una reacción, y para eso, es genial.

25

A mi personalmente me gustan las propiedades automotrices. ¿Qué hay de malo en guardar las líneas de código? Si desea hacer cosas en getters o setters, no hay problema para convertirlas a propiedades normales más adelante.

Como dijiste, podrías usar campos, y si querías agregarles lógica, los convertirías en propiedades. Pero esto podría presentar problemas con cualquier uso de la reflexión (¿y posiblemente en otro lugar?).

Además, las propiedades le permiten establecer diferentes niveles de acceso para el eliminador y el colocador que no puede hacer con un campo.

Supongo que es lo mismo que la palabra clave var. Una cuestión de preferencia personal.

39

Los tres grandes inconvenientes a la utilización de campos en lugar de propiedades son:

  1. Usted no puede DataBind a un campo mientras que lo que pueda para una propiedad
  2. Si usted comienza el uso de un campo, se puede' t más tarde (fácilmente) cambiarlos a una propiedad
  3. Hay algunos atributos que se pueden agregar a una propiedad que no se puede agregar a un campo
+6

"Si comienzas a usar un campo, no podrás cambiarlo (fácilmente) a una propiedad", perdón, pero ¿por qué? – Homam

+6

@Homam Principalmente, cualquier código de consumidor que utilice la reflexión en sus campos se rompería, ya que tendrían que cambiar de usar FieldInfo a PropertyInfo. – WCWedin

+8

@Homam Además, cambiar un campo a una propiedad rompe la compatibilidad binaria, lo que requiere que todos los consumidores del campo vuelvan a compilarse. – Odrade

4

Uso auto-propiedades todo el tiempo. Antes de C# 3 no podía molestarme con todo el tipeo y solo usaba variables públicas.

El único que extraño es ser capaz de hacer esto:

public string Name = "DefaultName"; 

usted tiene que cambiar los valores por defecto en sus constructores con propiedades. :-(tediosa

+0

~ Sé que esto es como un dólar tarde y un día corto, pero prueba http://msdn.microsoft.com/en-us/library/system.componentmodel.defaultvalueattribute.aspx – jcolebrand

+1

@drachenstern, mira la gran caja amarilla en esa página. DefaultValueAttribute solo le proporciona algo que puede usarse por reflexión para indicar cuál debe ser el valor predeterminado. No establece el valor para usted. –

+0

@Matthew Whited ~ Buena llamada, no debe haber notado la caja amarilla deslumbrante porque uso el scriptfree, se mezcló, pero c'est la vie ... – jcolebrand

4

Creo que cualquier constructo que es intuitivo y reduce las líneas de código es una gran ventaja.

Ese tipo de características son las que hacen lenguajes como Ruby tan potentes (Eso características y dinámicas, que también ayudar a reducir el exceso de código)

Rubí ha tenido esto todo el tiempo como:.

attr_accessor :my_property 
attr_reader :my_getter 
attr_writer :my_setter 
2

el único problema que tengo con ellos es que ellos no van lo suficientemente lejos la misma versión del compilador que agregó. propiedades automáticas, métodos parciales agregados. Por qué no juntaron los dos está más allá de mí. Un simple "parcial On <PropertyName> Changed" hubiera hecho estas cosas realmente útiles.

+0

Puede poner varios métodos parciales dentro de otro método. Crear un auto-patrón de algún tipo para ellos sería confuso. –

53

Sí, hace solo código de guardado. Son millas más fáciles de leer cuando tienes muchas. Son más rápidos de escribir y más fáciles de mantener. Guardar código siempre es un buen objetivo.

Se pueden establecer diferentes ámbitos:

public string PropertyName { get; private set; } 

Para que la propiedad sólo se puede cambiar dentro de la clase. Esto no es realmente inmutable, ya que aún puede acceder al establecimiento privado a través de la reflexión.

A partir de C# 6 también puede crear verdaderos readonly propiedades - es decir, propiedades inmutables que no pueden ser cambiadas fuera del constructor:

public string PropertyName { get; } 

public MyClass() { this.PropertyName = "whatever"; } 

en tiempo de compilación que se convertirán:

readonly string pName; 
public string PropertyName { get { return this.pName; } } 

public MyClass() { this.pName = "whatever"; } 

En las clases inmutables con muchos miembros, esto ahorra mucho código en exceso.

+0

"Para que no pierda ninguna funcionalidad". ¿cómo los depura? – wal

+1

@wal - ¿Qué hay para depurar? Desde ese punto de vista, básicamente se trata de variables miembro. – Keith

+0

En el ejemplo de carteles originales, ¿cómo se encuentra cuando myObj.¿El título está cambiando de un valor a otro? – wal

1

Una cosa a tener en cuenta aquí es que, a mi entender, esto es solo azúcar sintáctica en el extremo C# 3.0, lo que significa que el IL generado por el compilador es el mismo. Estoy de acuerdo en evitar la magia negra, pero de todos modos, menos líneas para la misma cosa suele ser algo bueno.

1

En mi opinión, siempre debe utilizar auto-propiedades en lugar de campos públicos. Dicho esto, aquí hay un compromiso:

Comience con un campo internal usando la convención de nomenclatura que usaría para una propiedad.La primera vez que sea

  • necesita el acceso al campo de fuera de su montaje, o
  • necesario adjuntar lógica a un captador/definidor

hacer esto:

  1. cambiar el nombre campo
  2. hacerlo privado
  3. agregar una propiedad pública

Su código de cliente no necesita cambios.

Algún día, sin embargo, su sistema crecerá y lo descompondrá en conjuntos separados y múltiples soluciones. Cuando eso sucede, cualquier campo expuesto volverá a perseguirte porque, como mencionó Jeff, changing a public field to a public property is a breaking API change.

8

Las propiedades automáticas son una magia tan negra como cualquier otra cosa en C#. Una vez que lo piensas en términos de compilar hasta IL en lugar de expandirse a una propiedad normal de C#, es mucho menos magia negra que muchos otros constructos de lenguaje.

0

Uso CodeRush, es más rápido que las propiedades automáticas.

Para hacer esto:

private string title; 
public string Title 
{ 
    get { return title; } 
    set { title = value; } 
} 

requiere ocho pulsaciones de teclado total.

+4

Si mantengo presionadas las teclas CTRL y V, puedo pegar muchas y muchas cosas,/realmente rápido /, pero eso no lo hace "mejor". ¿Cómo responde esto la pregunta original? – JBRWilkinson

0

bien con fragmentos de código un auto-propiedad del mismo nombre sería siete pulsaciones de teclas en total;)

17

Una cosa que nadie parece haber mencionado es la forma de auto-propiedades no son por desgracia útil para objetos inmutables (generalmente inmutables estructuras). Debido a que realmente debería hacer:

private readonly string title; 
public string Title 
{ 
    get { return this.title; } 
} 

(donde el campo es inicializado en el constructor a través de un parámetro pasado, y luego es de sólo lectura.)

Así que esto tiene ventajas sobre un simple get/private set autopropiedad.

+0

Si tiene una estructura que cambia cualquier propiedad, se genera una nueva estructura. Esto solo sería un problema si quisiera un tipo de referencia internamente inmutable; no veo la razón por la que alguna vez necesite uno. – Keith

+0

@Keith: su primera frase parece ser objetivamente incorrecta. – Domenic

+0

@Domenic: Creo que está limitando su definición de estructuras a inmutables. – maxwellb

0

@Domenic: Yo no lo entiendo .. no se puede hacer esto con propiedades auto-?:

public string Title { get; } 

o

public string Title { get; private set; } 

Es esto lo que se refiere?

+0

Puede (el último; el primero no se compilará), pero el campo no es inmutable dentro de su objeto. – Domenic

+0

Palabra de advertencia, solo las estructuras son inmutables cuando se marcan solo, las clases son simplemente no asignables. – Guvante

2

Es simple, es corto y si desea crear una implementación real dentro del cuerpo de la propiedad en algún momento, no romperá la interfaz externa de su tipo.

Tan simple como eso.

22

De Bjarne Stroustrup, creador de C++:

particular me gusta clases con una gran cantidad de funciones get y set. Eso es a menudo una indicación de que no debería haber sido una clase en primer lugar. Es solo una estructura de datos. Y si realmente es una estructura de datos, conviértala en una estructura de datos.

¿Sabes qué? El tiene razón. ¿Con qué frecuencia está simplemente envolviendo campos privados en un get y set, sin realmente hacer nada dentro del get/set, simplemente porque es lo "orientado a objetos" que hacer? Esta es la solución de Microsoft al problema; son básicamente campos públicos a los que puedes vincular.

+1

Realmente creo que esto debería tener más puntos. Demasiadas personas ven las propiedades automotrices como una luz verde para escribir clases horriblemente encapsuladas (o no encapsuladas para nada) que son poco más que un campo público glorificado. Por supuesto, esto es más un problema con la forma en que las personas usan la herramienta que con la herramienta en sí, pero creo que es importante mencionarlo cuando se discuten las propiedades en general. – kai

0

Mi mayor queja con las propiedades automotrices es que están diseñadas para ahorrar tiempo, pero a menudo me parece que tengo que expandirlas en propiedades completas más adelante.

Lo que le falta a VS2008 es un explotar la propiedad propia refactor.

El hecho de que tengamos un campo de encapsulado refactor hace que la forma en que trabajo más rápido sea simplemente usar campos públicos.

11

Siempre creo propiedades en lugar de campos públicos porque puede usar propiedades en una definición de interfaz, no puede usar campos públicos en una definición de interfaz.