C # restituisce una variabile come sola lettura da get; impostato;

Giuro che ho visto un esempio di questo, ma ho cercato su Google un po ‘e non riesco a trovarlo.

Ho una class che ha un riferimento ad un object e ha bisogno di avere un GET; metodo per questo. Il mio problema è che non voglio che nessuno sia in grado di giocherellare con esso, cioè voglio che ottengano una versione di sola lettura di esso, (nota che devo essere in grado di alterarlo dalla mia class).

Grazie

No, non c’è modo di farlo. Ad esempio, se si restituisce un List (e non è immutabile), i chiamanti potranno aggiungere voci.

Il modo normale attorno a questo è di restituire un wrapper immutabile, ad es. ReadOnlyCollection .

Per altri tipi mutabili, potrebbe essere necessario clonare il valore prima di restituirlo.

Si noti che la semplice restituzione di una visualizzazione interfaccia immutabile (ad esempio, la restituzione di IEnumerable anziché di List ) non impedirà a un chiamante di eseguire il cast del tipo mutabile e di mutare.

EDIT: Nota che, a parte ogni altra cosa, questo tipo di preoccupazione è uno dei motivi per cui i tipi immutabili rendono più facile ragionare sul codice 🙂

Restituisce un riferimento a un’interfaccia ridotta:

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

Questo non è ansible. Ottieni e imposta gli accessor ai tipi di riferimento ottieni e imposta il riferimento all’object. È ansible impedire le modifiche al riferimento utilizzando un setter privato (o interno), ma non è ansible impedire le modifiche all’object stesso se è esposto da un getter.

Se l’object non è troppo complicato / esteso, scrivi attorno a esso un involucro.

per esempio:

 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; } } } 

Quindi ora tutto ciò che fai è dare al tuo codice cliente un’istanza della class AWrapper in modo che possano usare solo ciò che tu permetti loro di vedere.

questo potrebbe essere un po ‘complicato e potrebbe non essere scalabile se la tua class base non è impostata su pietra, ma per la maggior parte delle situazioni semplici potrebbe semplicemente fare il trucco. Penso che questo sia chiamato un modello di facciata (ma non citatemi su quello =))

La tua domanda si legge come stai cercando:

 public PropertyName { get; private set; } 

Ma poi, date le risposte finora non sono sicuro di interpretare correttamente la tua domanda. Inoltre, chi sono io per interrogare Jon Skeet? 🙂

Sono d’accordo con ReadOnlyCollection

Vedi il mio codice semplice:

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

}

ReadOnlyCollection non ha aggiunto il metodo in modo che l’utente non possa aggiungere delle proprietà. Ma non c’è alcuna garanzia che l’utente possa modificare gli oggetti chiamando i loro metodi ….

Ho affrontato questo problema in un certo modo. Ho una class CategoryViewModel, che ha una proprietà Category che voglio privata di sola lettura:

 public CategoryViewModel { private Category { get; } } 

In effetti, voglio che venga esportato in sola lettura in un’altra class. Tuttavia non posso fare una cosa simile. Nel mio caso (forse aiuterà alcuni altri ragazzi), voglio aggiungerlo a un repository. L’unico modo che ho trovato è di avere una funzione con il repository come param 1, e un’azione come param 2:

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

Così, da altrove, posso fare una cosa del genere:

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

Questo può aiutare altri a esporre la proprietà solo per determinati casi e in grado di gestirli.