2010-02-17 16 views
16

Hay situaciones en las que declarar variables miembro en la parte superior de mi clase y declarará también tienen una propiedad de acceso o establecer que la variable miembro, pero me pregunto si la propiedad es necesaria si la variable sólo se va a acceder y configurar desde dentro de la clase y en ningún otro lado, entonces, ¿cuál es la ventaja de utilizar una propiedad para acceder y establecer una variable miembro en lugar de solo hacerlo directamente a la variable miembro misma? Aquí está un ejemplo:¿Diferencia entre la variable miembro y la propiedad miembro?

public class Car 
{ 

    int speed; //Is this sufficient enough if Car will only set and get it. 

    public Car(int initialSpeed) 
    { 
     speed = initialSpeed; 
    } 

    //Is this actually necessary, is it only for setting and getting the member 
     //variable or does it add some benefit to it, such as caching and if so, 
     //how does caching work with properties. 
    public int Speed 
    { 
     get{return speed;} 
     set{speed = value;} 
    } 

     //Which is better? 
     public void MultiplySpeed(int multiply) 
     { 
      speed = speed * multiply; //Line 1 
      this.Speed = this.Speed * multiply; //Line 2 

      //Change speed value many times 
      speed = speed + speed + speed; 
      speed = speed * speed; 
      speed = speed/3; 
      speed = speed - 4; 

     } 
} 

En lo anterior, si yo no tengo la velocidad propiedad para establecer y obtener la velocidad variable, y decido cambiar la velocidad int a int SPD, voy a tener que cambiar de velocidad a spd en todas partes se utiliza, sin embargo, si uso una propiedad como velocidad para establecer y obtener la velocidad, voy a tener que cambiar la velocidad a la del SPD en el get y set de la propiedad, por lo que en mi método MutilplySpeed, cosas como anteriormente this.Speed ​​= this.Speed ​​+ this.Speed ​​+ this.Speed ​​no se romperá.

+0

posible duplicado de [¿Cuál es la diferencia entre un campo y una propiedad en C#?] (Http: // stackoverflow.com/questions/295104/what-is-the-difference-between-a-field-and-a-property-in-c) – nawfal

Respuesta

22

Si la variable es private, voy a menudo no crear una propiedad para ello.Si lo es, de ninguna manera, expuesta en el exterior del tipo, siempre mostrarse a través de una propiedad por diferentes razones:

  • puede que no sea necesaria hoy en día, pero si llega a ser necesario más adelante se trata de un cambio importante
  • enlace de datos funciona sólo en propiedades, no en los campos (creo, no un usuario de enlace de datos grande)
  • permite insertar validaciones, la tala, los puntos de interrupción cuando se accede al valor

Además, si el campo está expuesta a través de una propiedad, siempre accedo a ella a través de la propiedad, incluso dentro de e clase.

actualización
En respuesta a sus muestras de códigos actualizadas: hay una serie de cosas a considerar en torno al diseño código aquí.

  • Legibilidad vs. velocidad
  • Otros efectos secundarios
  • "atomicidad"

Una pieza típica de consejo (que me parece muy bien) es "escribir para mayor claridad, la prueba de rendimiento" . Eso significa que cuando escribe su código, su primera preocupación debe ser si está claro lo que hace el código cuando lo mira. Esto es a menudo (pero no siempre) más importante que la velocidad bruta del código. Escribe optimizaciones de velocidad cuando hayas establecido dónde lo ganas. El acceso a una propiedad será un poco más lento que leer el campo directamente, pero en la mayoría de los casos, la diferencia será insignificante (si es que se puede medir).

Atomicity puede ser un problema. Dado el código de muestra, tenemos el campo speed, que está expuesto públicamente a través de la propiedad Speed. Si el método MultiplySpeed necesita realizar varias actualizaciones del valor, esos valores intermedios estarán disponibles a través de la propiedad Speed en momentos diferentes mientras el cálculo está en curso. Esto es cierto independientemente de si actualiza el campo directamente o a través de la propiedad. En casos como este, tal vez sea mejor primero poner el valor en una variable local, usar eso para los cálculos y asignar el valor de esa variable a la propiedad cuando haya terminado.

Por último, otros efectos secundarios. Podría ser que cambiar el valor de Speed debería provocar un evento (como SpeedChanged). En casos como ese, también es probable que sea una buena idea no hacer la actualización hasta que se complete el cálculo.

me gusta pensar acerca de la propiedad como un contratoy el campo de aplicación como . Cualquiera (excepto el núcleo de mi tipo) que necesite el valor debería usar el contrato. Depender de la implementación debe hacerse solo si hay buenas razones para eludir el contrato.

Y sí, si encapsula el acceso al campo en la propiedad, naturalmente, cambiar el nombre del campo requerirá menos actualizaciones (y tal vez también el nombre del campo sea menos importante).

espero que tenga sentido, y no es demasiado fuera de tema;)

+0

Las propiedades también son accesibles/configurables a través de la reflexión –

+0

Estoy de acuerdo con el uso de la propiedad incluso en la clase, incluso en el constructor. Es bueno saber que su lógica de validación es * always * siendo llamada. –

+0

+1 para usar un campo a través de una propiedad incluso desde adentro, ya que evita errores desagradables "setter-doesnt-run-when-it-it-should". – OregonGhost

0

Una cosa que se olvidó de mencionar, propiedades le ayudará a cabo cuando extiende su clase. Si su clase está diseñada adecuadamente las variables dentro de la clase base debe ser private. Sin las propiedades reales public propiedades que es. No tendría forma de acceder a estas variables privadas desde su clase extendida. Estamos hablando público vs privado y no estoy incluido protegido por una razón :).

Sólo algunas notas vale la pena mencionar:

  • propiedades ayudante cuando una clase se extiende
  • propiedades a mí que el código sea un poco más fácil de leer (además this.privateVariable Verson PublicPropertyVariableName)
  • propiedades pueden asegúrese de leer solo, conjuntos privados, público obtiene etc. (mucho más legible para otros programadores). Consideremos un caso en el que un identificador necesita un encuentro público, sino un conjunto privado
  • Personalmente a mí muchos se hace/conjuntos parece complicar código, hace que el código menos legible demasiado sintaxis innecesaria, extra
  • herencia/que se extiende a una clase extendida no le permite heredar variables privadas, las propiedades son la respuesta. (de nuevo no hay mención de protegido aquí, esa es una historia diferente)
  • Para mí, incluso si la clase tiene una variable privada, mis métodos de clase todavía usan la propiedad para acceder o usar esa variable privada
  • No te olvides la validación, hace que sea mucho más fácil validar especialmente la legibilidad.

Estas son algunas de las cosas más comunes (sin embargo, mis 2 centavos en la mayoría de ellos).

+0

Así que tomo de su respuesta que haciendo las variables privadas y usando propiedades para establecer y obtenerlos, me estoy aprovechando de la encapsulación? – Xaisoft

+0

También podría hacer eso con las variables protegidas. – cyberconte

1

Cosas como la validación pueden ser cubiertos en un solo lugar. El miembro está encapsulado, y desea tener que preocuparse por la validación y otras cosas del resto de su clase.

En su situación actual, realmente no hace la diferencia, pero cuando necesita cambiar la variable o agregar un comportamiento, es más fácil cuando usa propiedades, porque solo tiene un lugar donde necesita cambiarla .

1

no se le añade el almacenamiento en caché pero sí permite una interfaz consistente.

imagina que tienes que mejorar la velocidad añadiéndole una constante en el futuro. usar la variable miembro sería difícil donde la propiedad permite esta manipulación.

También internamente en la clase debe volver a acceder a la propiedad por consistencia (imagine el escenario anterior donde tenía una clase que accedió directamente a la variable miembro).

1

La única razón real que conozco es si se accede al campo desde fuera del ensamblaje. En ese caso, si desea agregar funcionalidades livianas a ese campo (tal vez establecer un indicador Sucio o validar un cambio) debe cambiarlo a una propiedad que cambie la forma en que lo ve el ensamblado llamante, que también necesitará reconstrucción. . En casos muy raros, es posible que descubra que no tiene control sobre ese conjunto, entonces tiene un problema.

No permita que los fanáticos de OO le digan que es filosóficamente incorrecto usar campos públicos, aunque podría estar de acuerdo en que las propiedades automáticas hacen que el argumento sea algo discutible.

+2

"No deje que los fanáticos de OO le digan que es filosóficamente incorrecto usar campos públicos, aunque podría estar de acuerdo en que las propiedades automáticas hacen que el argumento sea algo discutible". No soy fanático de OO pero es una mala práctica. Todas las variables miembro deben ser privadas. – JonH

+0

Aprecio los diferentes puntos de vista. – Xaisoft

+0

¿Por qué, JonH? No me malinterpretes, solía pensar lo mismo; Todavía lo hago por hábito si soy honesto. Pero desafiado a explicar por qué, no tengo una mejor respuesta que la que acabo de dar. – pdr

8

Estoy de acuerdo con Frederik's answer. Una cosa que hace que sea un poco menos trabajo seguir su consejo es usar propiedades automáticas. Esas son solo propiedades que generan automáticamente la lógica getter/setter estándar. No obtiene ninguna validación, pero siempre puede reemplazar la propiedad automática por una estándar más adelante. Este reemplazo no es un cambio de última hora.

Aquí he reemplazado la propiedad Speed ​​en su ejemplo con una propiedad automática. Observe que la variable miembro desaparece y su clase debe acceder a ella a través de la propiedad.

public class Car 
{ 
    public Car(int initialSpeed) 
    { 
     Speed = initialSpeed; 
    } 

    public int Speed { get; set; } 

    public void MultiplySpeed(int multiply) 
    { 
     Speed *= multiply; 
    } 
} 

También puede usar otro sabor llamado "get with private set". Esto significa que el getter es público, pero el setter es privado. Se define así:

public int Speed { get; private set; } 

En cuanto a su pregunta sobre el this. prefijo, por lo general es irrelevante. La única vez que importa es cuando ha definido un parámetro de método o una variable local con el mismo nombre que una variable miembro. Luego puede usar this para acceder a la variable miembro.

+0

Gracias por el ejemplo. – Xaisoft

1

El hecho es que no hay mucha diferencia entre un campo declarado públicamente y una propiedad pública con una tienda de respaldo privada si no hay una lógica adicional. Dicho esto, todavía se considera una mejor práctica para usar propiedades.

Y antes de que todos se den cuenta de la extensibilidad, recuerde que si luego necesita agregar funcionalidad, puede mantener el nombre con la propiedad e introducir un nuevo nombre para la tienda de respaldo para que no sea un cambio radical.

0

En mi opinión, el diseño del idioma está roto. No debería haber dos formas de hacer cosas que tengan tanta superposición semántica. Las propiedades/campos deberían haber proporcionado los beneficios de cualquiera de los enfoques dependiendo de cómo se usan. Si el programa hace un uso mínimo de las características de la propiedad, deberían actuar del mismo modo que los campos. Además, no debe haber una necesidad de declarar get vacío; y establecer; métodos en este caso. Las diferencias me parecen artificiales.

Es un lenguaje excelente; y bastante limpio en su mayor parte. Eso no significa que no deba mejorarse "la próxima vez".

Cuestiones relacionadas