C # devuelve una variable como solo lectura desde get; conjunto;

Juro que he visto un ejemplo de esto, pero he estado buscando en Google un poco y no puedo encontrarlo.

Tengo una clase que tiene una referencia a un objeto y necesito tener un GET; Método para ello. Mi problema es que no quiero que nadie pueda jugar con él, es decir, quiero que obtengan una versión de solo lectura (tenga en cuenta que debo poder modificarlo dentro de mi clase).

Gracias

No, no hay manera de hacer esto. Por ejemplo, si devuelve una List (y no es inmutable), las personas que llaman podrán agregar entradas.

La forma normal de evitar esto es devolver un envoltorio inmutable, por ejemplo, ReadOnlyCollection .

Para otros tipos mutables, es posible que deba clonar el valor antes de devolverlo.

Tenga en cuenta que el solo hecho de devolver una vista de interfaz inmutable (por ejemplo, devolver IEnumerable lugar de List ) no impedirá que una persona que llama vuelva al tipo mutable y lo mute.

EDITAR: Tenga en cuenta que, aparte de cualquier otra cosa, este tipo de preocupación es una de las razones por las que los tipos inmutables hacen que sea más fácil razonar sobre el código 🙂

Devuelva una referencia a una interfaz reducida:

  interface IFoo string Bar { get; } class ClassWithGet public IFoo GetFoo(...); 

Esto no es posible. Obtener y configurar los accesores a los tipos de referencia obtener y establecer la referencia al objeto. Puede evitar que se realicen cambios en la referencia utilizando un configurador privado (o interno), pero no puede evitar que se realicen cambios en el objeto si lo expone un captador.

Si el objeto no es demasiado complicado / extenso, escriba una envoltura alrededor de él.

por ejemplo:

 class A { public string strField = 'string'; public int intField = 10; } class AWrapper { private A _aObj; public AWrapper(A aobj) { _aObj = A; } public string strField { get { return _aObj.strField; } } public int intField { get { return _aObj.intField; } } } 

Así que ahora todo lo que haces es darle a tu código de cliente una instancia de la clase AWrapper para que solo puedan usar lo que les permites ver.

esto puede complicarse un poco y puede no escalarse bien si su clase base no está en piedra, pero para la mayoría de las situaciones, puede hacer el truco. Creo que esto se llama un patrón de fachada (pero no me cites en eso =))

Su pregunta se lee como si estuviera buscando:

 public PropertyName { get; private set; } 

Pero luego, dadas las respuestas hasta ahora, no estoy seguro de que esté interpretando su pregunta correctamente. Además, ¿quién soy yo para interrogar a Jon Skeet? 🙂

Estoy de acuerdo con ReadOnlyCollection

Ver mi código simple:

  private List _devices; public readonly System.Collections.ObjectModel.ReadOnlyCollection Devices { get { return (_devices.AsReadOnly()); } 

}

ReadOnlyCollection dosen’t tiene método Add, por lo que el usuario no puede agregarle propiedades. Pero no hay garantía de que si el usuario puede modificar objetos llamando a sus métodos …

He enfrentado este problema de cierta manera. Tengo una clase CategoryViewModel, que tiene una categoría de propiedad que quiero privada de solo lectura:

 public CategoryViewModel { private Category { get; } } 

De hecho, quiero que se exporte como solo lectura a otra clase. Sin embargo no puedo hacer tal cosa. En mi caso (tal vez ayude a otros tipos), quiero agregarlo a un repository. La única forma que encontré es tener una función con el repository como param 1 y una acción como param 2:

 public void ApplyAction(ICategoryRepository repo, Action action) { action(repo, Category); } 

Así, desde otra parte, puedo hacer tal cosa:

  categoryViewModel.ApplyAction(_repository, (r, c) => r.MarkForInsertOrUpdate(c)); 

Esto puede ayudar a otros a exponer su propiedad solo para ciertos casos y puede gestionarlos.