Cómo implementar una propiedad de solo lectura

Necesito implementar una propiedad de solo lectura en mi tipo. Además, el valor de esta propiedad se establecerá en el constructor y no se va a modificar (estoy escribiendo una clase que expone comandos UI enrutados personalizados para WPF, pero no importa).

Veo dos formas de hacerlo:

  1. class MyClass { public readonly object MyProperty = new object(); } 
  2.  class MyClass { private readonly object my_property = new object(); public object MyProperty { get { return my_property; } } } 

Con todos estos errores de FxCop que dicen que no debería tener variables de miembro público, parece que el segundo es el camino correcto para hacerlo. ¿Correcto?

¿Hay alguna diferencia entre una propiedad de solo obtener y un miembro de solo lectura en este caso?

Agradecería cualquier comentario / consejo / etc.

Versionado
Creo que no hace mucha diferencia si solo está interesado en la compatibilidad de la fuente.
Usar una propiedad es mejor para la compatibilidad binaria ya que puede reemplazarla por una propiedad que tenga un setter sin romper el código comstackdo según su biblioteca.

Convención:
Estás siguiendo la convención. En casos como este, donde las diferencias entre las dos posibilidades son relativamente menores, seguir la convención es mejor. Un caso en el que podría volver a morderte es el código basado en la reflexión. Es posible que solo acepte propiedades y no campos, por ejemplo, un editor / visor de propiedades.

Publicación por entregas
Cambiar de un campo a otro probablemente romperá muchos serializadores. Y AFAIK XmlSerializer solo serializa propiedades públicas y no campos públicos.

Usando una propiedad automática
Otra variación común es usar una propiedad automática con un setter privado. Si bien esto es corto y una propiedad, no hace cumplir la legibilidad. Entonces prefiero los otros.

El campo Readonly es autodocumenting
Sin embargo, hay una ventaja del campo:
De un vistazo deja claro que, en realidad, es inmutable (salvo la reflexión). Mientras que en el caso de una propiedad, solo puede ver que no puede cambiarla, por lo que deberá consultar la documentación o la implementación.

Pero para ser honesto, utilizo el primero bastante a menudo en el código de la aplicación ya que soy flojo. En las bibliotecas, normalmente soy más completo y sigo la convención.

C # 6.0 agrega propiedades de solo lectura

 public object MyProperty { get; } 

Entonces, cuando no necesita soportar comstackdores más antiguos, puede tener una propiedad verdaderamente de solo lectura con un código que sea tan conciso como un campo de solo lectura.

La segunda forma es la opción preferida.

 private readonly int MyVal = 5; public int MyProp { get { return MyVal;} } 

Esto asegurará que MyVal solo se pueda asignar en la inicialización (también se puede configurar en un constructor).

Como ya habías notado, de esta manera no expones a un miembro interno, lo que te permite cambiar la implementación interna en el futuro.

Con la introducción de C # 6 (en VS 2015), ahora puede tener propiedades get only, en las que el campo de respaldo implícito es de readonly (es decir, los valores pueden asignarse en el constructor pero no en otros):

 public string Name { get; } public Customer(string name) // Constructor { Name = name; } private void SomeFunction() { Name = "Something Else"; // Compile-time error } 

Y ahora también puede inicializar propiedades (con o sin setter) en línea:

 public string Name { get; } = "Boris"; 

Volviendo a la pregunta, esto le brinda las ventajas de la opción 2 (el miembro público es una propiedad, no un campo) con la brevedad de la opción 1.

Desafortunadamente, no proporciona una garantía de inmutabilidad a nivel de la interfaz pública (como en el punto @ autodescifrado de @CódigosInChaos), porque para un consumidor de la clase, no tener establecedor es indistinguible de tener un establecedor privado.

Puedes hacerlo:

 public int Property { get { ... } private set { ... } } 

Estoy de acuerdo en que la segunda forma es preferible. La única razón real para esa preferencia es la preferencia general de que las clases .NET no tengan campos públicos. Sin embargo, si ese campo es de solo lectura, no puedo ver cómo habría otras objeciones reales aparte de la falta de coherencia con otras propiedades. La diferencia real entre un campo de solo lectura y una propiedad de solo obtención es que el campo de solo lectura proporciona una garantía de que su valor no cambiará durante la vida del objeto y que una propiedad de solo obtener acceso no lo hace.

El segundo método es preferido debido a la encapsulación. Ciertamente puede hacer que el campo de solo lectura sea público, pero eso va en contra de las expresiones idiomáticas de C # en las que tiene acceso de datos a través de propiedades y no campos.

El razonamiento detrás de esto es que la propiedad define una interfaz pública y si la implementación de respaldo a esa propiedad cambia, no termina rompiendo el rest del código porque la implementación está oculta detrás de una interfaz.