C # restituiscono una variabile in sola lettura da get; impostato;
-
06-09-2019 - |
Domanda
Giuro che ho visto un esempio di questo, ma sono stato googling per un po 'e non riesco a trovarlo.
Ho una classe che ha un riferimento a un oggetto e la necessità di avere un GET; Metodo per esso. Il mio problema è che io non voglio che nessuno sia in grado di giocherellare con esso, vale a dire che voglio loro di ottenere una versione di sola lettura di esso, (nota che ho bisogno di essere in grado di modificare dall'interno mia classe).
Grazie
Soluzione
No, non c'è modo di fare questo. Per esempio, se si torna un List<string>
(e non è immutabile), allora i chiamanti essere in grado di aggiungere voci.
Il modo normale giro questo è per restituire un involucro immutabile, ad esempio ReadOnlyCollection<T>
.
Per altri tipi mutabili, potrebbe essere necessario clonare il valore prima di restituirlo.
Si noti che solo restituendo una vista interfaccia immutabile (ad esempio ritornando IEnumerable<T>
anziché List<T>
) non si fermerà un chiamante dalla fusione nel tipo mutabile e mutazione.
EDIT: Si noti che, a parte ogni altra cosa, questo tipo di preoccupazione è una delle ragioni per le quali tipi immutabili rendono più facile ragionare sul codice:)
Altri suggerimenti
restituire un riferimento a un'interfaccia stripped-down:
interface IFoo
string Bar { get; }
class ClassWithGet
public IFoo GetFoo(...);
Questo non è possibile. Accesso get e set per fare riferimento a tipi ottenere e impostare il riferimento all'oggetto. È possibile impedire modifiche al riferimento utilizzando un setter privata (o interno), ma non si può impedire che le modifiche all'oggetto in sé se è esposto da un getter.
Se l'oggetto non è troppo complicato / estesa poi scrivere un wrapper attorno ad esso.
Ad 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;
}
}
}
Così ora tutto ciò che fai è dare il vostro codice client un'istanza della classe AWrapper in modo che essi possono utilizzare solo ciò che si consente loro di vedere.
questo può diventare un po 'complicato e potrebbe non scala bene se la classe base non è scolpito nella pietra, ma per la maggior parte situazione semplice possa solo fare il trucco. Credo che questo si chiama un modello di facciata (ma non citare me su quel =))
La tua domanda si legge come siete alla ricerca di:
public PropertyName { get; private set; }
Ma poi, dato le risposte finora non sono sicuro di interpretare la sua domanda. Inoltre, chi sono io per dubbio Jon Skeet? :)
Sono d'accordo con ReadOnlyCollection
Vedere il mio semplice codice:
private List<Device> _devices;
public readonly System.Collections.ObjectModel.ReadOnlyCollection<Device> Devices
{
get
{
return (_devices.AsReadOnly());
}
}
ReadOnlyCollection dosen't ha Aggiungi metodo in modo utente non posso aggiungere oggetti da it.But ther è alcuna garanzia che se l'utente può modificare gli oggetti chiamando i loro metodi ....
Ho affrontato questo problema in un certo modo. Ho una classe CategoryViewModel, che hanno una categoria di proprietà che voglio privato di sola lettura:
public CategoryViewModel
{
private Category { get; }
}
In realtà, io voglio che sia esportato in sola lettura per altra classe. Tuttavia non posso fare una cosa simile. Nel mio caso (forse aiuterà alcuni altri ragazzi), voglio aggiungere che a un repository. L'unico modo che ho trovato è quello di avere una funzione con il repository come param 1, ed un'azione come param 2:
public void ApplyAction(ICategoryRepository repo, Action<ICategoryRepository, Category> action)
{
action(repo, Category);
}
Come quella, da qualche altra parte, non posso fare una cosa:
categoryViewModel.ApplyAction(_repository, (r, c) => r.MarkForInsertOrUpdate(c));
Questo può aiutare gli altri ad esporre lì proprietà solo per certains casi e in grado di gestire.