2010-01-30 30 views
28

Soy bastante nuevo en C#, y creo que las propiedades son maravillosas. Tan maravilloso, de hecho, que no puedo ver ninguna ventaja real en el uso de campos, en cambio. Incluso para los campos privados, parece que la flexibilidad y la modularidad que ofrecen las propiedades pueden, en el mejor de los casos, ahorrarle dolores de cabeza graves y, en el peor de los casos, no tener ningún efecto.¿Por qué utilizar campos en lugar de propiedades?

La única ventaja que puedo ver para los campos es que puede inicializarlos en línea. Pero la mayoría de las veces, desea inicializarlos en el constructor, de todos modos. Si no está utilizando la inicialización en línea, ¿hay alguna razón para no usar propiedades todo el tiempo?

Editar: Algunas personas han mencionado la necesidad de hacer una copia de seguridad de las propiedades con los campos (de forma explícita o automática). Deje que aclare mi pregunta: ¿Hay alguna razón para usar los campos excepto para hacer una copia de seguridad de las propiedades? Es decir, ¿hay algún momento en que SomeType someField; sea preferible a SomeType SomeProperty { get; set; }?

Editar 2: DanM, Skurmedel y Seth dieron respuestas realmente útiles. Acepté el de DanM, ya que es el más completo, pero si alguien resumiera sus respuestas en una sola respuesta, estaría encantado de aceptarlo.

+2

duplicado de http://stackoverflow.com/questions/295104/what-is-the-difference-between-a-field-and-a-property- in-c – user73993

+2

así que vamos a cerrarlo –

+6

No, creo que esta es una pregunta excelente, que también es muy sutil. Definitivamente diferente. –

Respuesta

21

Normalmente, las propiedades necesitan un campo de respaldo a menos que sean simples "propiedades automáticas" de getter/setter.

Por lo tanto, si sólo está haciendo ...

public string Name { get; set; } // automatic property 

... que no es necesario un campo, y estoy de acuerdo, no hay razón para tener uno.

Sin embargo, si estás haciendo ...

public string Name 
{ 
    get { return _name; } 
    set 
    { 
     if (value = _name) return; 
     _name = value; 
     OnPropertyChange("Name"); 
    } 
} 

... necesita que _name campo de respaldo.

Para las variables privadas que no requieren ninguna lógica especial de obtención/configuración, es realmente una decisión de juicio si se debe hacer una propiedad automática privada o solo un campo. Usualmente hago un campo, luego, si necesito que sea protected o public, lo cambiaré a una propiedad automática.

actualización

Como se ha señalado por Yassir, si utiliza las propiedades automáticas, todavía hay un campo que está al acecho detrás de las escenas, simplemente no es algo que realmente tiene que escribir. Entonces, la conclusión es que las propiedades no almacenan datos, sino que proporcionan acceso a los datos. Los campos son los que realmente contienen los datos. Entonces, los necesitas aunque no puedas verlos.

Actualización 2

cuanto a su pregunta revisada ...

¿Hay algún momento que SomeType SomeField; es preferible a SomeType SomeProperty { get; set; }?

... una cosa que viene a la mente: Si usted tiene un campo privado, y (según la convención de campos privados) que llamarlo _name, que las señales a usted y cualquiera que lea el código que se está trabajando directamente con datos privados. Si, por otro lado, haces de todo una propiedad, y (de acuerdo con la convención de propiedades) llama a tu propiedad privada Name, ahora no puedes simplemente mirar la variable y decir que se trata de datos privados. Entonces, usar solo propiedades quita algo de información. No he intentado trabajar con todas las propiedades para evaluar si esa es información crucial, pero definitivamente algo se pierde.

Otra cosa, más leve, es que public string Name { get; set; } requiere más tipeo (y es un poco más desordenado) que private string _name.

+1

Debería mencionar que el compilador crea un campo para cada propiedad de auto –

+5

Creo que el punto de los carteles es: incluso su campo _name en el ejemplo que usted dio podría ser una propiedad privada auto implementada. En teoría, no es necesario que conozca realmente los campos, solo son un detalle de la implementación de cómo funcionan las propiedades, podrían estar completamente ocultos para el desarrollador por el compilador como detalles de implementación, al igual que los registros de la CPU. –

+1

@Mark, usted es técnicamente correcto, pero usar una propiedad privada como una "propiedad de respaldo" parecería violar las convenciones, lo que haría que la intención de su código no sea clara para quienes necesitan leerla o mantenerla. También crea un problema de nomenclatura.Si la propiedad pública es 'Nombre', ¿cómo llamaría a la propiedad privada? Si lo llamas '_name' o' _Name', es probable que otras personas lean tu código y formen conclusiones incorrectas sobre si esa variable es una propiedad o un campo. Dicho esto, tal vez algún día la distinción entre propiedades y campos desaparecerá. – devuxer

3

Hay no motivo para exponer públicamente los campos.

Si pública expone un campo que no se puede cambiar la fuente de la información, desde el defination en línea en el archivo de configuración sin refactorización. \

Se puede usar un campo de ocultar datos internos. Raramente estoy a favor de eso, solo uso campos cuando estoy haciendo algo para ocultarlo públicamente y usarlo en una propiedad. (es decir, no estoy utilizando la generación automática de propiedades)

+0

No solo eso, exponer públicamente los campos está en contra del paradigma de OOP en términos de ocultar información dentro de una clase concreta ... – t0mm13b

+4

No creo que esto realmente responda a su pregunta. Él quiere saber por qué los campos son recomendados sobre las propiedades en ciertas situaciones. –

+5

La afirmación de que no hay motivos para exponer públicamente los campos es incorrecta; si ese fuera el caso, la característica sería ilegal. Hay una serie de buenas razones para exponer públicamente un campo. Por ejemplo, construir una estructura mutable para usar en un escenario de interoperabilidad con un objeto COM heredado. Esto es particularmente relevante cuando los campos del objeto se pasan como argumentos "ref" o "out" a un método de objeto COM heredado. –

2

Los campos y las propiedades no son intercambiables. Supongo que lo que estás diciendo es acceder a campos privados a través de propiedades privadas. Hago esto cuando tiene sentido, pero en su mayor parte, no es necesario. El optimizador JIT tendrá acceso en línea a un campo privado a través de una propiedad privada en la mayoría de los casos de todos modos. Y envolver un campo privado en una propiedad privada no se considera un cambio radical ya que los miembros privados no son parte de su interfaz.

Personalmente, quisiera nunca exponer cualquier campo de instancia protegida/pública. Sin embargo, generalmente es aceptable exponer un campo público estático con un modificador de solo lectura, siempre que el tipo de campo sea inmutable. Esto se ve a menudo con los campos estáticos SomeStruct.Empty.

11

Las propiedades son una cosa maravillosa, pero hay gastos generales asociados con el acceso a la propiedad. No necesariamente es un problema, sino algo a tener en cuenta.

Evitar el uso excesivo de la Propiedad captadores y definidores

mayoría de las personas no se dan cuenta de que la propiedad getters y setters son similares a los métodos cuando se trata de gastos generales; es principalmente la sintaxis que los diferencia. El compilador incluirá un getter o setter de propiedad no virtual que no contenga instrucciones distintas al acceso de campo, pero en muchos otros casos esto no es posible. Debes considerar cuidadosamente tu uso de las propiedades; desde dentro de una clase, acceda directamente a los campos (si es posible) y nunca llame ciegamente a las propiedades repetidamente sin almacenar el valor en una variable. Dicho todo esto, ¡esto no significa que debas usar campos públicos!

Fuente: http://dotnet.sys-con.com/node/46342

+5

"Un compilador o instalador de propiedades no virtuales que no contenga instrucciones que no sean el acceso de campo será subrayado por el compilador" El caso al que se refiere (propiedades privadas implementadas automáticamente) entrará en esta categoría, por lo que no afectará el rendimiento de acuerdo a esto. –

2

Como otros han señalado, necesitará un campo privado para respaldo de las propiedades de todos modos.

También hay una ventaja de velocidad en el uso de campos sobre las propiedades. En el 99.99% de los casos no importará. Pero en algunos podría.

3

Los campos son el único lugar donde puede almacenar estado.Las propiedades son en realidad solo un par de métodos con sintaxis especial que les permite mapearse al método get o set, dependiendo de cómo se estén usando: si una propiedad modifica o accede al estado, ese estado todavía tiene que ser almacenado en un campo .

No siempre ve los campos. Con las propiedades automáticas C# 3, el compilador crea el campo para usted. Pero todavía está allí. Además, las propiedades automáticas tienen algunas limitaciones importantes (por ejemplo, sin soporte INotifyPropertyChanged, sin lógica comercial en los setters) que significan que a menudo son inapropiadas, y usted necesita crear un campo explícito y una propiedad definida manualmente de todos modos.

Según David's answer, tienes razón si hablas de una API: casi nunca deseas que el estado interno (campos) forme parte de la API.

9

Si quieres tener algo readonly tienes que usar un campo ya que no hay forma de decirle a una propiedad automática que genere un campo de solo lectura.

Lo hago con bastante frecuencia.

ejemplo Contrived:

class Rectangle 
{ 
    private readonly int _width; 
    private readonly int _height; 

    public Rectangle(int width, int height) 
    { 
     _width = width; 
     _height = height; 
    } 

    public int Width { get { return _width; } } 
    public int Height { get { return _height; } } 
} 

Esto significa nada dentro de rectángulo puede alterar la anchura o la altura después de la construcción. Si uno intenta, el compilador se quejará.

Si en lugar de eso hubiera usado una propiedad automática con un setter privado, el compilador no me protegería de mí mismo.

Otra razón que veo es, si un dato no tiene que estar expuesto (permanecer private) ¿por qué hacer una propiedad?

+1

Esto es bueno saberlo. ¿Por qué no puedes hacer 'public readonly int Width {get; conjunto; } '? –

+0

No tengo idea. Solo puedo adivinar; tal vez fue cortado a favor de otras características, o no vieron la necesidad. Tendrás que preguntarle a Eric Lippert acerca de eso :) – Skurmedel

+0

Como solo puedes jugar en los campos de solo lectura en el constructor (o cuando los declaras), no puedo imaginar qué sintaxis sería buena para declarar una propiedad de solo lectura. . – Skurmedel

3

La sintaxis para los campos es mucho más rápida de escribir que para las propiedades, por lo que cuando es seguro usar un campo (privado para la clase) ¿por qué no usarlo y guardar esa escritura adicional? Si las propiedades implementadas automáticamente tuvieran la breve sintaxis concisa corta y tuvieras que hacer un trabajo extra para crear un campo viejo simple, las personas podrían comenzar a usar propiedades en su lugar. Además, es una convención ahora en C#. Así es como piensan las personas, y es lo que esperan ver en el código. Si haces algo diferente de lo normal, confundirás a todos.

Pero podría preguntar por qué la sintaxis de los campos no crea una propiedad implementada automáticamente en lugar de un campo, por lo que obtiene lo mejor de ambos mundos: propiedades en todas partes y una sintaxis concisa.

Hay una razón muy simple por lo que todavía tiene que tener campos explícitos:

C# 1.0 no tenía todas estas características agradables que tenemos ahora, por lo que los campos eran un hecho de la vida - realmente no se podía vive sin ellos Montones y montones de código dependen de que los campos y las propiedades sean cosas visiblemente diferentes. Simplemente no se puede cambiar ahora sin romper toneladas de código.

También sospecho que hay implicaciones de rendimiento, pero quizás eso se pueda resolver con el jitter.

Así que estamos atrapados con los campos para siempre, y ya que están ahí y han tomado la mejor sintaxis, tiene sentido usarlos cuando sea seguro hacerlo.

+0

¿Por qué querrías tener propiedades todo el tiempo? ¿O te refieres a un modificador en el campo que le dijo que hiciera una propiedad (como se vería;))? – Skurmedel

+2

¿Por qué quiere tener dos sintaxis diferentes para "este es un miembro"? ;-) –

+0

En realidad, no necesitarías un modificador si todo fuera una propiedad. Ni siquiera necesitarías decir 'public int Foo {get; conjunto; } ' Simplemente diciendo 'public int Foo;' estaría bien porque si todo es una propiedad, sería seguro, y el código es más conciso. Pero obviamente esto nunca puede suceder en C#. La decisión de tener dos cosas diferentes, "campos" y "propiedades", se establece en piedra y no se puede cambiar. –

4

No veo por qué usarías autopropiedades privadas.¿Qué ventaja hay para

private int Count {get; set;} 

sobre

private int count 
+1

La propiedad predeterminada puede ser virtual, por lo que puede ser anulada, y puede controlar obtener y establecer el acceso de forma independiente (por ejemplo, hacer que get accessor public y el set accessor esté protegido). ¿Qué sucede si no los necesita al principio, pero es posible que los necesite más adelante? Luego, podría comenzar con un campo y usar una propiedad más adelante, a menos que esté accediendo a campos o propiedades a través de la reflexión. Entonces ... la ventaja está ahí solo algunas veces. – apollodude217

+1

También vale la pena señalar que si convierte de campo a propiedad más adelante porque los requisitos cambian, todo lo que haga referencia al campo debe recompilarse también. –

4

Aunque estoy de acuerdo con lo que perciben como la "intención" en la declaración de David Basarab: "No hay ninguna razón para exponer públicamente campos," I' Me gustaría añadir un énfasis ligeramente diferente:

Modificaría la cita de David arriba para que diga: "No hay ninguna razón para exponer públicamente campos ... fuera de una clase ... excepto a través de la opción consciente de encapsular los campos en Propiedades a través de los cuales el acceso es rigurosamente contro llenó

propiedades no son simplemente una "chapa" de la sintaxis sobre los campos "añadidas a" C#: son una característica del lenguaje fundamental diseñada por buenas razones, entre ellas:

  1. controlar lo que está expuesta y no expuesta clases externas (encapsulación, ocultación de datos)

  2. permitiendo que se realicen ciertas acciones cuando se accede o establece una propiedad: acciones que se expresan mejor en el conjunto de propiedades 'get y', en lugar de ser 'elevadas' a definidas externamente métodos.

  3. Las interfaces por diseño no pueden definir 'campos: pero pueden definir Propiedades.

buen diseño orientado a objetos significa tomar decisiones conscientes acerca de "estado":

  1. campos variables locales: qué estado se encuentra privado a un método y transitorios: variables locales normalmente sólo válidos en el ámbito de un cuerpo de método, o incluso con una vida útil "tan estrecha" como dentro del alcance de algo así como un ciclo 'for'. Por supuesto, también puede considerar las variables de parámetro en un método como "local".

  2. campos de instancia de clase: qué estado es privado para una clase, y tiene existencia independiente para cada instancia de una clase, pero es muy probable que se requiera su uso en varios lugares de la clase.

  3. campos de instancias estáticas: qué estado será una propiedad de la clase solamente, independientemente del número de instancias de la clase.

  4. estado expuesto deliberadamente y conscientemente "fuera" de la clase: la idea clave es que hay al menos un nivel de indirección interpuesto entre la clase y los "consumidores" de los datos que expone la clase. El "lado opuesto" de "exposición" es, por supuesto, la intención consciente de ocultar (encapsular, aislar) el código de implementación.

    a. a través de propiedades públicas: todos los aspectos de esto bien cubiertos en todas las otras respuestas aquí

    b. a través de los indexadores

    c. a través de los métodos

    d. las variables estáticas públicas se encuentran generalmente en clases de utilidad, que a menudo son clases estáticas.

sugerimos que revise: MSDN on 'Fields ... MSDN on Properties ... MSDN on Indexers

0

velocidad. Si un campo se establece o lee miles de millones de veces en el transcurso de una simulación, entonces desea utilizar un campo y no una propiedad para evitar la sobrecarga de una llamada secundaria. Conforme a OO (DDD?) Tanto como sea posible, en estos casos, recomendaría recurrir a los campos solo en la clase dedicada a representar a algún tipo de persona de "valor". La lógica debe mantenerse al mínimo. Más bien, tenga un creador personal o un asesor personal.

Pero si tiene estos problemas, entonces probablemente no esté programando C++ y no C#, ¿verdad?

9

Sólo trate utilizando una propiedad cuando se utiliza árbitro de entrada/salida args:

someObject.SomeMethod(ref otherObject.SomeProperty); 

No va a compilar.

0

Hay varias respuestas buenas (parciales) de @Seth (los campos tienen un mejor rendimiento, por lo que en un contexto privado puede ser útil en su beneficio cuando tiene sentido), @Skurmedel (los campos pueden ser de solo lectura), @ Jenk (los campos se pueden usar para ref/out). Pero me gustaría agregar uno más:

Puede usar la sintaxis de inicialización optimizada para establecer el valor de un campo, pero no una propiedad. es decir:

private int x = 7; 

vs

private int x { get; set; } 

// This must go in the constructor, sometimes forcing you to create 
// a constructor that has no other purpose. 
x = 7; 
+1

Esto ahora es posible con C# 6 – Gaspa79

Cuestiones relacionadas