2011-11-02 10 views

Respuesta

51

El primero es un campo de solo lectura, mientras que el segundo se compila como un par de métodos (y todas las lecturas de la propiedad ProductLocation se compilan en llamadas al método get correspondiente y se compilan en llamadas al método set; internamente, estos métodos leerán/escribirán en un campo interno, generado automáticamente, que no es de solo lectura). Diría que la diferencia más importante es la seguridad de hilos! (¿cómo? seguir leyendo!)

El uso básico de la clase se verá exactamente lo mismo: el código en otras clases solo podrá leer el valor, no cambiarlo. Además, el código para leer el valor se verá exactamente igual (por ejemplo, print(myInstace.ProductLocation); aquí no se puede decir cómo se ha declarado, genial, ¿eh?)

La primera y más trivial diferencia es que la propiedad con private setter permite instancias de la misma clase para modificar el valor, mientras que en el caso de la propiedad de solo lectura, ni siquiera el objeto en sí podrá cambiar el valor.

Ahora, para la seguridad de la rosca. El atributo readonly en el campo cambiará su semántica de visibilidad de memoria cuando trabaje con varios subprocesos (al igual que los campos final de Java).

Un campo readonly solo se puede asignar a la declaración o en el constructor. El valor asignado a un campo readonly no se puede cambiar (al menos no en una forma normal) y se garantiza que cada subproceso verá el valor inicializado correctamente después de que el constructor devuelva. Por lo tanto, un campo readonly es intrínsecamente seguro para subprocesos.

Para lograr el mismo hilo de seguridad con la propiedad, tendría que agregar algo de sincronización en su código, que es propenso a errores. Puede llevar a bloqueos, carreras de datos o rendimiento reducido, dependiendo del caso, y especialmente si no tiene experiencia.

lo tanto, si el valor representa algo que semánticamente no se puede cambiar después de la construcción del objeto, no se debe declarar una incubadora privada (esto implicaría que el objeto podría cambiarlo). Vaya por el campo de solo lectura (y tal vez declare que es privado y declare una propiedad pública con solo un getter accediendo al campo! Esta es la forma preferida, ya que no es bueno exponer los campos, es mejor exponer solo los métodos; son muchas las razones que explican por qué en this answer)

+3

Para mí, la diferencia más importante es la propiedad de inmutabilidad, ya que en realidad tiene algún valor semántico. – Freek

6

la primera de ellas (utilizando readonly) significará que el objeto no puede incluso modificar el valor de su propio campo, una vez que el objeto ha creado una instancia, y otros nunca puede modificarla.

El segundo (utilizando private set) significará ese objeto puede modificar el valor de su campo después ha sido instanciado, pero otros no pueden modificarlo.

Yo usaría el primero para algo que usted sabe no cambiará, y usará el último para algo donde el valor puede cambiar, pero no desea que otros lo cambien.

18

En general, no se recomienda en .NET exponer públicamente los campos de miembros, estos deben estar envueltos por una propiedad. Así que vamos a suponer que podría tener

private readonly string productLocation; 
public string ProductLocation { get { return productLocation; } } 

vs

public string ProductLocation { get; private set; } 

En esta configuración, e ignorando lo que podría ser capaz de lograr a través de la reflexión, la semántica es que en el primer caso, la variable productLocation puede solo se inicializará en su lugar y en el constructor de la clase. Otros miembros de la clase no pueden alterar el valor. Los consumidores externos no tienen la capacidad de establecer el valor.

En la segunda versión, los consumidores externos siguen sin tener acceso para establecer el valor. Sin embargo, la clase en sí misma puede cambiar el valor en cualquier momento. Si todo lo que tiene es un DTO (es decir, una clase que solo transporta datos, no tiene una lógica expresada a través de métodos), entonces, en esencia, esto no es muy diferente de la versión readonly. Sin embargo, para las clases con métodos, esos métodos podrían alterar el valor detrás de ProductLocation.

Si desea aplicar el concepto de campo inmutable después de la construcción, use readonly. Pero para un DTO, podría optar por la opción private set;, principalmente porque es un código menos repetitivo.

+2

Solo tenga en cuenta que la opción 'private set;' no es segura para subprocesos. –

+0

En realidad, se recomienda envolver el campo Readonly. Soy un desarrollador perezoso y esa es la razón por la que estoy preguntando. cadena de solo lectura pública ProductLocation es definitivamente una versión más corta, y debido a esto parece ser mejor para mí. – Krzysztof

4

El primero es un campo cuyo valor se puede establecer en solo en la instanciación.

El segundo es un propiedad cuyo valor se puede establecer en cualquier momento (pero sólo por su objeto que contiene).


Corrección: La propiedad se puede establecer en cualquier momento por cualquier instancia de la misma clase (y no sólo por su objeto que contiene).

+2

Esto no es correcto. La propiedad se puede establecer en cualquier momento ** por cualquier instancia de la misma clase ** (y no * solo por su objeto que contiene *). –

+0

+1 Bruno gracias por la aclaración. –

+0

@BrunoReis, y ¿cuál es la diferencia entre una instancia y un objeto contenedor? Como sin una instancia, no tienes un objeto. ¿Podría alguien aclarar? – usefulBee

7

Con C# 6.0inicializador de auto-propiedad hay menos repetitivo manera de hacer

private readonly string productLocation; 
public string ProductLocation { get { return productLocation; } } 

Cuál es

public string ProductLocation { get; } 

Esto es de sólo lectura. Solo se inicializó desde el constructor o en línea. No puede ser editado después de la inicialización. (Inmutable desde cualquier lugar)

Sin embargo, si utiliza un conjunto privado;

public string ProductLocation { get; private set } 

Esto es solo de lectura desde el exterior. Pero se puede inicializar en cualquier momento en cualquier lugar dentro de la clase.Y puede ser editado dentro de su ciclo de vida por la clase misma. (Mutable de clase, inmutable desde el exterior)

+0

¡Buena actualización, hermano! Gracias :) –

Cuestiones relacionadas