Variable privada vs propiedad?

41

Al establecer un valor en una variable dentro de una clase la mayor parte del tiempo se nos presentan dos opciones:

private string myValue;
public string MyValue
{
   get { return myValue; }
   set { myValue = value; }
}

¿Existe una convención que determine cómo debemos asignar valores a las variables dentro de nuestras clases? Por ejemplo, si tengo un método dentro de la misma clase, debo asignarlo usando la propiedad o la variable privada. Lo he visto hecho de ambas maneras, así que me preguntaba si esta es una elección o el rendimiento es un factor (menor, probablemente).

    
pregunta Edward 02.02.2012 - 18:21

8 respuestas

22

Lo llevaría un paso más allá y lo llevaría a 3 casos. Aunque hay variaciones en cada una, esta es la regla que uso la mayoría del tiempo cuando programo C #.

En el caso 2 y 3, siempre vaya al Accesor de propiedades (no a la variable de campo). Y en el caso 1, se salvará incluso de tener que hacer esta elección.

1.) Propiedad inmutable (pasada al constructor, o creada en tiempo de construcción). En este caso, utilizo una variable de campo, con una propiedad de solo lectura. Elijo esto en lugar de un setter privado, ya que un setter privado no garantiza la inmutabilidad.

public class Abc
{ 
  private readonly int foo;

  public Abc(int fooToUse){
    foo = fooToUse;
  }

  public int Foo { get{ return foo; } }
}

2.) Variable POCO. Una variable simple que puede obtener / establecer en cualquier ámbito público / privado. En este caso, solo usaría una propiedad automática.

public class Abc
{ 
  public int Foo {get; set;}
}

3.) ViewModel propiedades de enlace. Para las clases que admiten INotifyPropertyChanged, creo que necesitas una variable de campo de respaldo privada.

public class Abc : INotifyPropertyChanged
{
  private int foo;

  public int Foo
  {
    get { return foo; }
    set { foo = value;  OnPropertyChanged("foo"); }
  }
}
    
respondido por el Sheldon Warkentin 02.02.2012 - 19:21
18

En general, yo diría que asignar al campo en el constructor y usar la propiedad en cualquier otro lugar. De esta manera, si alguien agrega funcionalidad a la propiedad, no la perderá en ninguna parte.

Ciertamente no es un factor de rendimiento. El optimizador incluirá un simple obtención o configuración para usted y el código final de MSIL probablemente será idéntico.

    
respondido por el pdr 02.02.2012 - 18:32
4

Depende.

Primero debes preferir las propiedades automáticas cuando sea posible:

public string MyValue {get;set;}

En segundo lugar, el mejor enfoque probablemente sería utilizar las propiedades, si tienes alguna lógica allí, probablemente deberías pasarlo por ti mismo, especialmente si esa lógica es la sincronización de subprocesos.

Pero también debes tener en cuenta que podría obstaculizar tu rendimiento (un poco), si estás sincronizando incorrectamente, puedes bloquearte, y en algún momento la ruta correcta es seguir la lógica de la propiedad.

    
respondido por el AK_ 02.02.2012 - 18:34
3

Bueno, el enfoque directo al punto sería simplemente asignarlo a la propia variable, ya que estás dentro del método de una clase y controlas el comportamiento de la clase, de todos modos.

Pero el punto principal de las propiedades es que abstraen la variable. Mientras que una propiedad tan simple como la de su ejemplo no tiene ningún uso sobre una simple variable de miembro público, las propiedades generalmente hacen (o deberían hacer) cosas adicionales dentro de sus captadores y definidores. Y si desea que estas cosas se realicen automáticamente al cambiar la propiedad dentro de la clase, entonces, por supuesto, es más limpio trabajar en la propiedad en lugar de que la variable no tenga que cambiar cada asignación de variable cuando el comportamiento de configuración de la propiedad cambia.

Solo tienes que razonar sobre ello conceptualmente. La propiedad es en realidad un identificador para acceder a algún estado interno del objeto, que puede estar compuesto por más de una variable miembro. Por lo tanto, debe preguntarse si desea cambiar solo el estado interno subyacente (o solo una parte de él) o la propiedad abstracta que representa a este estado en su totalidad, y la mayoría de las veces es la última, ya que generalmente desea que su objeto siempre tenga un estado consistente.

    
respondido por el Christian Rau 02.02.2012 - 18:38
2

Si existe alguna posibilidad de que la implementación de la propiedad get / set cambie algunas veces más tarde (por ejemplo, si desea llamar a set o se agregará un mecanismo de evaluación perezoso a su función get ) ), entonces puede ser una buena idea que su código dentro de la clase usará la propiedad en casi todos los casos, excepto en los casos (lo más probable es que sean raros) en los que explícitamente no desee ese evento o perezoso Mecanismos de evaluación a utilizar.

De todos modos, haga lo que haga, es muy probable que cuando cambie la implementación de la propiedad más tarde de esa manera, tenga que buscar en todos los lugares dentro de su clase que accedan a esa propiedad para verificar si realmente la propiedad será Se accederá o se utilizará la variable privada.

    
respondido por el Doc Brown 02.02.2012 - 18:32
2

Siempre uso la propiedad pública.

A menudo, una lógica que siempre debería ejecutarse cuando se establece la propiedad se agrega al método set de una propiedad, y al establecer el campo privado, en lugar de eso, el definidor público omite cualquier lógica allí.

Tiene un comentario sobre MVVM que lleva a esta pregunta y creo que esto es aún más importante cuando se trabaja con MVVM. Muchos objetos generan una notificación PropertyChange en el setter, y otros objetos pueden suscribirse a este evento para ejecutar alguna acción cuando cambian propiedades específicas. Si configura la variable privada, estas acciones nunca se ejecutarán a menos que también aumente manualmente el evento PropertyChanged .

    
respondido por el Rachel 02.02.2012 - 19:53
1

En general, depende de usted lo que debe hacer con una propiedad y su campo de respaldo al obtener / configuración.

En la mayoría de los casos, solo para ser coherente en todo el código, debe usar accesores públicos donde estén disponibles y sean apropiados. Eso te permite refactorizar con un mínimo cambio de código; si el método que realiza esta configuración debe eliminarse de la clase y colocarse en otro lugar donde el campo de respaldo ya no esté disponible (como una clase base), ¿a quién le importa? Estás usando algo que está disponible donde sea que la clase misma haga el trabajo. El campo de respaldo, en la mayoría de los casos, es un detalle de implementación; nadie fuera de tu clase debería saber que existe.

La situación principal en la que puedo pensar cuando debería usar el campo de respaldo y NO el acceso a la propiedad es cuando el accesorista tiene lógica adicional (validación o actualización de otra información de estado en la clase) que no desea ejecutar. La población inicial de un objeto es un ejemplo; puede tener una clase que usa dos valores de propiedad para calcular un tercero, que también se almacena en un campo de respaldo (por razones de persistencia). Al inicializar una nueva copia de los datos dados de ese objeto desde la base de datos, los que acceden a la propiedad y cada uno de ellos recalculan el tercer valor pueden quejarse si el otro valor necesario no está establecido. Al usar los campos de respaldo para establecer los valores iniciales de estas dos (o tres) propiedades, omite la lógica de validación / cálculo hasta que la instancia se encuentre en un estado lo suficientemente consistente como para que la lógica funcione normalmente.

    
respondido por el KeithS 02.02.2012 - 20:35
0

Usa siempre el que tenga sentido. Sí, ya sé que suena bastante falso hasta el punto de no ser una respuesta.

El punto de propiedades es proporcionar una interfaz a través de la cual pueda acceder de manera segura a un modelo de datos. Para la mayoría de las situaciones, siempre desea acceder de forma segura al modelo de datos a través de esa interfaz, como por ejemplo:

public Foo Bar
{
  get { return _bar; }
  set { _bar = doSomethingTo(value); }
}

Pero en otras situaciones, puede que simplemente esté utilizando una propiedad como una vista de un modelo de datos:

public Double SomeAngleDegrees
{
  get { return SomeAngleRadians * 180 / PI; }
  set { SomeAngleRadians = value * PI / 180; }
}

Si tiene sentido usar la forma de radianes de SomeAngle , entonces, por supuesto, úsala.

Al final, asegúrate de beber tu propia ayuda de Kool. Tu API pública debe ser lo suficientemente resistente para trabajar internamente.

    
respondido por el zzzzBov 03.02.2012 - 02:45

Lea otras preguntas en las etiquetas