2010-07-22 27 views
159

me he dado cuenta de que el C# propiedad constructo también se puede utilizar con un modificador privada acceso:¿Hay alguna razón para usar propiedades privadas en C#?

private string Password { get; set; } 

Aunque esto es técnicamente interesante, no me puedo imaginar cuando lo uso ya que un ámbito privado implica incluso menos ceremonia:

private string _password; 

y no puedo imaginar que cuando alguna vez necesito estar poder internamente obtener pero no conjunto o conjunto pero no obtener un campo privado:

private string Password { get; } 

o

private string Password { set; } 

pero tal vez no es un caso de uso con clases anidadas/heredadas o quizás cuando get/set puede contener lógica en lugar de simplemente devolver el valor de la propiedad, aunque tendería a mantener las propiedades estrictamente simples y permitir que los métodos explícitos hagan cualquier lógica, p. GetEncodedPassword().

¿Alguien usa propiedades privadas en C# por alguna razón o es solo una de esas construcciones de código técnico técnicamente posibles pero rara vez usadas?

Adición

Niza respuestas, leer a través de ellos que sacrificaron estos usos para las propiedades privadas:

  • cuando los campos privados necesitan ser cargados de forma liviana
  • cuando los campos privados necesitan lógica adicional o se calculan valores
  • ya que los campos privados pueden ser difíciles de depurar
  • para "presentar un contrato a usted mismo"
  • para convertir internamente/simplificar una propiedad expuesta como parte de serialización
  • envolviendo variables globales para ser utilizado dentro de su clase
+3

"cadena privada Contraseña {get;}" ni siquiera es legal C#. No compilará –

+2

@eric true, obtiene el error "... Password.get" debe declarar un cuerpo porque no está marcado como abstracto o externo. Las propiedades implementadas automáticamente deben definir los accesadores get y set. " Simplemente asumí que funcionaría, ya que utilizo 'public string Password {get {return _password; }} 'a menudo. –

+0

La técnica recomendada por las propiedades privadas es * autoencapsulación * - ver: http://sourcemaking.com/refactoring/self-encapsulate-field – LBushkin

Respuesta

151

Los uso si necesito guardar un valor en caché y quiero cargarlo de forma perezosa.

private string _password; 
private string Password 
{ 
    get 
    { 
     if (_password == null) 
     { 
      _password = CallExpensiveOperation(); 
     } 

     return _password; 
    } 
} 
+0

+1 ¡Este es mi uso estándar también! También me gusta la posibilidad de agregar lógica extra más adelante como @Reed Copsey mencionó anteriormente. –

+0

+1 Lo mismo aquí ... –

+13

un buen patrón común para esto es 'return _password ?? (_password = CallExpensiveOperation()); ' – Marc

4

yo los utilizo cada vez en cuando. Pueden facilitar la depuración de situaciones cuando puede colocar fácilmente un punto de interrupción en la propiedad o puede agregar una declaración de registro, etc.

También puede ser útil si luego necesita cambiar el tipo de datos en algunas manera o si necesita usar la reflexión.

+0

Ídem; si hay una lógica involucrada en un get/set, a veces puedo usar una propiedad privada o protegida. En general, depende de la cantidad de lógica: lógica simple que haré en la propiedad, mucha lógica, generalmente usaré una función auxiliar. Lo que hace que el código sea más sostenible. – TechNeilogy

32

tal vez no es un caso de uso con clases anidadas/heredadas o tal vez en un get/set puede contener lógica en lugar de simplemente devolviendo el valor de la propiedad

Yo personalmente uso esto incluso cuando no necesita lógica en el getter o setter de una propiedad. El uso de una propiedad, incluso una privada, ayuda a proteger su código a futuro para que pueda agregar la lógica a un getter más tarde, si es necesario.

Si considero que una propiedad puede requerir una lógica adicional, a veces la incluiré en una propiedad privada en lugar de utilizar un campo, para no tener que cambiar el código más adelante.


En un caso semi-relacionados (aunque diferente a su pregunta), que muy a menudo utilizan los emisores privados en las propiedades públicas:

public string Password 
{ 
    get; 
    private set; 
} 

Esto le da un captador pública, pero mantiene la incubadora privado.

+0

+1 tiene sentido: "Si siento que una propiedad puede requerir una lógica adicional, a veces la incluiré en una propiedad privada en lugar de usar un campo, para no tener que cambiar mi código más tarde". –

+5

emisores privados <3 – Earlz

2

Es una práctica común modificar solo miembros con métodos get/set, incluso privados. Ahora, la lógica detrás de esto es que usted sepa que su get/set siempre se comporta de una manera particular (por ejemplo, desencadenando eventos) lo que no parece tener sentido ya que estos no se incluirán en el esquema de propiedad ... pero los viejos hábitos se mueren duro.

2

Tiene mucho sentido cuando hay una lógica asociada con el conjunto de propiedades o get (piense en la inicialización lenta) y la propiedad se usa en algunos lugares de la clase.

Si es solo un campo de respaldo recto? Nada viene a la mente como una buena razón.

11

El único uso que se me ocurre

private bool IsPasswordSet 
{ 
    get 
    { 
     return !String.IsNullOrEmpty(_password); 
    } 
} 
+0

1 para la clase útil de las propiedades que se calcula a partir de otras variables privadas –

+0

Por qué no usar un método privado 'IsPasswordSet private bool() { regreso! Cadena.IsNullOrEmpty (_password); } ' – Roman

5

Propiedades y campos no son uno a uno. Una propiedad se trata de la interfaz de una clase (ya sea que se trate de su interfaz pública o interna), mientras que un campo trata acerca de la implementación de la clase. Las propiedades no deben verse como una forma de exponer los campos, sino como una forma de exponer la intención y el propósito de la clase.

Al igual que usa propiedades para presentar un contrato a sus consumidores sobre lo que constituye su clase, también puede presentar un contrato para usted mismo por motivos muy similares. Entonces sí, uso propiedades privadas cuando tiene sentido. A veces, una propiedad privada puede ocultar detalles de implementación como la carga diferida, el hecho de que una propiedad es realmente un conglomerado de varios campos y aspectos, o que una propiedad necesita ser instanciada virtualmente con cada llamada (piense en DateTime.Now). Definitivamente hay momentos en los que tiene sentido hacer cumplir esto, incluso en ti mismo en el back-end de la clase.

+0

+1:" también puede presentar un contrato para usted mismo por motivos muy similares "tiene sentido –

16

La inicialización diferida es un lugar donde pueden estar ordenadas, p. Ej.

private Lazy<MyType> mytype = new Lazy<MyType>(/* expensive factory function */); 

private MyType MyType { get { return this.mytype.Value; } } 

// In C#6, you replace the last line with: private MyType MyType => myType.Value; 

A continuación, se puede escribir: this.MyType todas partes en lugar de this.mytype.Value y encapsular el hecho de que se crea una instancia perezosamente en un solo lugar.

Una cosa que es una pena es que C# no admite el alcance del campo de respaldo de la propiedad (es decir, declararlo dentro de la definición de propiedad) para ocultarlo completamente y garantizar que solo se pueda acceder a través de la propiedad.

+2

De acuerdo, sería tener el aspecto de alcance allí. –

+5

Utilizo esta misma técnica con frecuencia y también he deseado que un campo se pueda ubicar en un cuerpo de código. Es una característica agradable pero de baja prioridad. –

+3

@Eric Lippert - 'field-declaration' s dentro de' accessor-declarations' ha ocupado el puesto número 1 en mi lista de deseos C# durante mucho tiempo. Si pudiera diseñarlo e implementarlo en alguna versión futura (real), entonces le prepararé un pastel. –

14

Un buen uso para propiedades privadas solo obtener se calculan los valores. Varias veces he tenido propiedades que son de solo lectura y solo hago un cálculo sobre otros campos en mi tipo. No es digno de un método y no es interesante para otras clases, por lo que es propiedad privada.

97

El uso principal de esto en mi código es la inicialización lenta, como otros han mencionado.

Otra razón para las propiedades privadas sobre los campos es que las propiedades privadas son mucho, mucho más fáciles de depurar que los campos privados. Frecuentemente quiero saber cosas como "este campo se está configurando inesperadamente, ¿quién es el primer interlocutor que establece este campo?" y es mucho más fácil si puedes poner un punto de interrupción en el setter y presionar "ir". Puedes poner logging allí. Puedes poner métricas de rendimiento allí. Puede colocar comprobaciones de coherencia que se ejecutan en la compilación de depuración.

Básicamente, se trata de: código es mucho más poderoso que los datos. Cualquier técnica que me permita escribir el código que necesito es buena. Los campos no le permiten escribir código en ellos, las propiedades sí.

+4

¿El "código es mucho más poderoso que los datos" está diciendo? Al buscar en Google devuelve referencias que te señalan. Solo quiero saber para poder citarlo correctamente cuando sea necesario. –

+15

@Joan: No lo sé. O me lo inventé, o escuché a alguien más decirlo y pensé "wow, debería robarlo totalmente, y luego olvidarme de quién lo robé". –

+2

Gracias Eric. Bueno, solo te acreditaré porque no quiero decir "cita anónima": O –

7

Los uso en serialización, con cosas como DataContractSerializer o protobuf-net que admiten este uso (XmlSerializer no). Es útil si se necesita para simplificar un objeto como parte de serialización:

public SomeComplexType SomeProp { get;set;} 
[DataMember(Order=1)] 
private int SomePropProxy { 
    get { return SomeProp.ToInt32(); } 
    set { SomeProp = SomeComplexType.FromInt32(value); } 
} 
5

Una cosa que hago todo el tiempo es tienda de las variables "globales"/cache en HttpContext.Current

private static string SomeValue{ 
    get{ 
    if(HttpContext.Current.Items["MyClass:SomeValue"]==null){ 
     HttpContext.Current.Items["MyClass:SomeValue"]=""; 
    } 
    return HttpContext.Current.Items["MyClass:SomeValue"]; 
    } 
    set{ 
    HttpContext.Current.Items["MyClass:SomeValue"]=value; 
    } 
} 
4

utilizo propiedades privadas para reducir el código para acceder a las propiedades secundarias que a menudo usar.

private double MonitorResolution 
    { 
     get { return this.Computer.Accesories.Monitor.Settings.Resolution; } 
    } 

Es útil si hay muchas propiedades secundarias.

Cuestiones relacionadas