Propiedades automáticas C # 3.0: ¿útiles o no? [cerrado]

155

Nota: Esto se publicó cuando comenzaba C #. Con el conocimiento de 2014, realmente puedo decir que las propiedades automáticas se encuentran entre las mejores cosas que le han pasado al lenguaje C #.

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

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

Ahora, con .NET 3.0, tenemos propiedades automáticas:

public string Title { get; set; }

Sé que esto es más una pregunta filosófica / subjetiva, pero ¿hay alguna razón para usar estas propiedades automáticas, excepto por 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 fanático de la magia negra.

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

Veo el beneficio de que guardo mucho código (uno frente a seis líneas) sin perder la capacidad de cambiar la lógica del captador / definidor más tarde, pero de nuevo ya puedo hacerlo simplemente declarando un campo público "Título de cadena pública" sin la necesidad de {get; conjunto; } bloque, por lo tanto, incluso guardando más código.

Entonces, ¿qué me estoy perdiendo aquí? ¿Por qué alguien querría usar propiedades automáticas?

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

Respuestas:

118

Los usamos todo el tiempo en Stack Overflow.

También puede estar interesado en una discusión de Propiedades vs. Variables públicas . En mi humilde opinión, eso es realmente una reacción, y para ese propósito, es genial.

Jeff Atwood
fuente
62

Sí, solo guarda el código. Es mucho más fácil de leer cuando tienes un montón de ellos. Son más rápidos de escribir y más fáciles de mantener. Guardar código siempre es un buen objetivo.

Puede establecer diferentes ámbitos:

public string PropertyName { get; private set; }

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

A partir de C # 6 también puede crear readonlypropiedades verdaderas , es decir, propiedades inmutables que no se pueden cambiar fuera del constructor:

public string PropertyName { get; }

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

En tiempo de compilación se convertirá en:

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

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

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

Keith
fuente
"Para que no pierdas ninguna funcionalidad". ¿Cómo los depuras?
wal
2
@wal: ¿qué hay para depurar? Desde ese punto de vista, básicamente se trata de variables miembro.
Keith el
66
@wal: puede ponerles un punto de interrupción, al igual que puede acceder a una variable miembro, simplemente no puede entrar en ellas. pero ¿Por qué querrías? Lo que realmente hacen las propiedades automáticas es trivial y autogenerado, si tienes errores, ese es un lugar en el que es extremadamente improbable que se encuentren.
Keith
3
Es posible que tengamos que llevar esto fuera de Keith. :)
wal
1
Pero bueno, suponga que tiene muchas llamadas de establecimiento a myObj.Title ... desea ver dónde cambia el valor de "texto" a nulo, es decir, un punto de corte condicional. ¿Cómo logras eso? ni siquiera puedes establecer un punto de interrupción en el setter
wal
45

Las tres grandes desventajas de usar campos en lugar de propiedades son:

  1. No puede enlazar datos a un campo mientras que puede a una propiedad
  2. Si comienza a usar un campo, no podrá cambiarlo (fácilmente) más tarde a una propiedad
  3. Hay algunos atributos que puede agregar a una propiedad que no puede agregar a un campo
lomaxx
fuente
77
"Si comienzas a usar un campo, no puedes (fácilmente) cambiarlo a una propiedad más tarde", lo siento, pero ¿por qué?
Homam
66
@Homam Principalmente, cualquier código de consumidor que use reflejo 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 compilar.
Odrade
1
Dejando a un lado los problemas de compilación y reflexión, es muy fácil encapsular campos usando Visual Studio: Ctrl-R + E le permitirá convertir un campo en una propiedad con captadores / establecedores apropiados. (o haga clic con el botón derecho en el campo, vuelva a factorizar, encapsule el campo).
JoeBrockhaus el
Los campos de @Hommam son valores (son variables) y las propiedades no lo son. Las cosas que podrían haberse compilado cuando era un campo podrían no serlo cuando es una propiedad.
Mark
29

Personalmente me encantan las propiedades automáticas. ¿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 en propiedades normales más adelante.

Como dijiste, podrías usar campos, y si quisieras agregarles lógica más tarde, los convertirías en propiedades. Pero esto podría presentar problemas con cualquier uso de la reflexión (y posiblemente en otros lugares).

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

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

Rayo
fuente
29

De Bjarne Stroustrup, creador de C ++:

Particularmente no me gustan las clases con muchas 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.

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

Giovanni Galbo
fuente
2
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) 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 mencionarla cuando se habla de propiedades en general.
sara
18

Una cosa que nadie parece haber mencionado es cómo las propiedades automáticas desafortunadamente no son útiles para objetos inmutables (generalmente estructuras inmutables). Porque para eso realmente deberías hacer:

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

(donde el campo se inicializa en el constructor a través de un parámetro pasado y luego es de solo lectura).

Esto tiene ventajas sobre una propiedad simple get/ private setautomática.

Domenic
fuente
Si tiene una estructura que cambia cualquier propiedad, resulta en una nueva estructura. Esto solo sería un problema si quisieras un tipo de referencia inmutable internamente. No puedo ver una razón por la que alguna vez necesitarías uno.
Keith
@Keith: Tu primera oración parece objetivamente incorrecta.
Domenic
3
¿No daría como public string Title { get; private set; }resultado exactamente lo mismo? Podrías cambiarlo desde dentro de la clase, por supuesto, pero si lo haces tienes otros problemas ...: p
Svish
2
@Svish - por que el argumento de la palabra clave de sólo lectura en C # no debe usarse nunca porque su uso significaría que estábamos escondiendo estos "problemas diferentes"
Zaid Masud
2
Solo quiero decir que desde un punto de vista de API externo, no haría mucha diferencia. Y así, las propiedades automáticas podrían usarse si se quisiera. Lo mejor sería, por supuesto, si pudieras hacer algo comopublic string Title { get; private readonly set; }
Svish
12

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

Theo
fuente
8

Las propiedades automáticas son tan mágicas como cualquier otra cosa en C #. Una vez que lo piensa en términos de compilar a IL en lugar de expandirlo a una propiedad normal de C # primero, es mucho menos magia negra que muchas otras construcciones de lenguaje.

ICR
fuente
5

Yo uso propiedades automáticas todo el tiempo. Antes de C # 3 no podía molestarme con todo el tipeo y solo usaba variables públicas.

Lo único que extraño es poder hacer esto:

public string Name = "DefaultName";

Debe cambiar los valores predeterminados a sus constructores con propiedades. tedioso :-(

Orion Edwards
fuente
44
Con los inicializadores de propiedad automática de C # 6, pronto podrá hacer esto: public string Name { get; set; } = "DefaultName"; blogs.msdn.com/b/csharpfaq/archive/2014/11/20/…
Carlos Muñoz
5

Creo que cualquier construcción que sea intuitiva Y reduzca las líneas de código es una gran ventaja.

Ese tipo de características es lo que hace que lenguajes como Ruby sean tan potentes (eso y características dinámicas, que también ayudan a reducir el exceso de código).

Ruby ha tenido esto todo el tiempo como:

attr_accessor :my_property
attr_reader :my_getter
attr_writer :my_setter
Mike Stone
fuente
2

El único problema que tengo con ellos es que no van lo suficientemente lejos. La misma versión del compilador que agregó propiedades automáticas, agregó métodos parciales. Por qué no pusieron los dos juntos está más allá de mí. Un simple "parcial en <PropertyName> cambiado" habría hecho que estas cosas fueran realmente muy útiles.

David Wengier
fuente
Puede poner múltiples métodos parciales dentro de otro método. Crear un patrón automático de algún tipo para ellos sería confuso.
Matthew Whited el
2

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

Tan sencillo como eso.

Omer van Kloeten
fuente
1

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

pbh101
fuente
1

En mi opinión, siempre debes usar las propiedades automáticas en lugar de los campos públicos. Dicho esto, aquí hay un compromiso:

Comience con un campo interno utilizando la convención de nomenclatura que usaría para una propiedad. Cuando tú tampoco

  • necesita acceso al campo desde fuera de su ensamblaje, o
  • necesita adjuntar lógica a un captador / definidor

Hacer esto:

  1. renombrar el campo
  2. hazlo privado
  3. agregar una propiedad pública

Su código de cliente no tendrá que cambiar.

Sin embargo, algún día su sistema crecerá y lo descompondrá en ensamblajes separados y múltiples soluciones. Cuando eso suceda, los campos expuestos volverán a atormentarte porque, como Jeff mencionó, cambiar un campo público a una propiedad pública es un cambio de API de última hora .

ESV
fuente
0

Yo 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 teclas en total.

Brian Leahy
fuente
55
Si mantengo presionadas las teclas CTRL y V, puedo pegar muchísimas cosas, / realmente rápido /, pero eso no lo hace 'mejor'. ¿Cómo responde esto a la pregunta original?
JBRWilkinson
0

Bueno, con fragmentos de código, una propiedad automática del mismo nombre sería siete pulsaciones de teclas en total;)

ICR
fuente
0

@Domenic: No lo entiendo ... ¿no puedes hacer esto con las propiedades automáticas ?:

public string Title { get; }

o

public string Title { get; private set; }

¿A esto te refieres?

Andrei Rînea
fuente
Puede (lo último; lo primero no se compilará), pero luego el campo no es inmutable dentro de su objeto.
Domenic
Una advertencia: solo las estructuras son inmutables cuando se marcan como de solo lectura, las clases simplemente no se pueden asignar.
Guvante
0

Mi mayor queja con las propiedades automáticas es que están diseñadas para ahorrar tiempo, pero a menudo encuentro que más tarde tengo que expandirlas a propiedades completas.

Lo que falta a VS2008 es un refactor de Autodestrucción de propiedad .

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

Johnno Nolan
fuente