2009-05-12 10 views
8

Ho una classe in C# che contiene un dizionario, che voglio creare e garantire nulla come aggiunto, modificato o rimosso da questo dizionario purché esista la classe che lo contiene.const dizionario in C#

readonly in realtà non aiuta, una volta ho provato e ho visto che posso aggiungere articoli dopo. Solo per esempio, ho creato un esempio:

public class DictContainer 
{ 
    private readonly Dictionary<int, int> myDictionary; 

    public DictContainer() 
    { 
     myDictionary = GetDictionary(); 
    } 

    private Dictionary<int, int> GetDictionary() 
    { 
     Dictionary<int, int> myDictionary = new Dictionary<int, int>(); 

     myDictionary.Add(1, 2); 
     myDictionary.Add(2, 4); 
     myDictionary.Add(3, 6); 

     return myDictionary; 
    } 

    public void Add(int key, int value) 
    { 
     myDictionary.Add(key, value); 
    } 

} 

voglio che il metodo Add non lavorare. Se possibile, non voglio nemmeno compilare. Eventuali suggerimenti?

In realtà, sono preoccupato perché è un codice che sarà aperto a molte persone per cambiare. Quindi, anche se nascondo il metodo Add, sarà possibile per qualcuno "innocentemente" creare un metodo che aggiunge una chiave o ne rimuove un'altra. Voglio che le persone guardino e sappiano che non dovrebbero cambiare il dizionario in alcun modo. Proprio come ho con una variabile const.

+2

Strani requisiti suggeriscono che il tuo progetto presenta problemi. Potresti voler ripensare a ciò che stai tentando qui. Altrimenti, puoi facilmente creare la tua implementazione che fa questo. – Will

+3

È possibile implementare il proprio dizionario. Domanda simile: http://stackoverflow.com/questions/35002/does-c-have-a-way-of-giving-me-an-immutable-dictionary –

risposta

12

Non c'è niente in .NET Framework per aiutarti qui, ma this post dà una buona implementazione di un generico ReadOnlyDictionary in C# . Implementa tutte le interfacce che potreste aspettarvi (IDictionary, ICollection, IEnumerable, ecc.) E come bonus, l'intera classe e i suoi membri sono completamente commentati con XML.

(ho astenuti dal pubblicare il codice qui, perché è davvero molto lungo con tutti i commenti XML.)

+3

+1 per "non pubblicare il codice qui"! Il collegamento alla fonte originale è sempre migliore; simile al credito dell'autore. – Cerebrus

+3

@Cerebrus: Sì, si dovrebbe sempre collegare prima la fonte originale - come dici tu, è meglio attribuirlo all'autore. La mia opinione è che se il codice/testo è abbastanza breve, di solito è utile * rispecchiarlo * qui (nel caso in cui il sito vada giù per esempio), ma in questo caso non è molto appropriato. – Noldorin

+1

Grazie per aver riferito il mio articolo :-). – Steven

3

Eh ... allora non definire il metodo Add ...

Mantenere la variabile myDictionary privato ed esporre un getter/indicizzatore in modo che possa essere letto solo dall'esterno quella classe ..

si chiede se manca completamente il punto

7

Nascondere il dizionario completamente. Fornisci semplicemente un metodo get sulla classe DictContainer che recupera elementi dal dizionario.

public class DictContainer 
{ 
    private readonly Dictionary<int, int> myDictionary; 

    public DictContainer() 
    { 
     myDictionary = GetDictionary(); 
    } 

    private Dictionary<int, int> GetDictionary() 
    { 
     Dictionary<int, int> myDictionary = new Dictionary<int, int>(); 

     myDictionary.Add(1, 2); 
     myDictionary.Add(2, 4); 
     myDictionary.Add(3, 6); 

     return myDictionary; 
    } 

    public this[int key] 
    { 
     return myDictionary[key]; 
    } 
} 
0
interface IReadOnlyDic<Key, Value> 
{ 
    void Add(Key key, Value value); 
} 
class ReadOnlyDic<Key, Value> : Dictionary<Key, Value>, IReadOnlyDic<Key, Value> 
{ 
    public new void Add(Key key, Value value) 
    { 
     //throw an exception or do nothing 
    } 
    #region IReadOnlyDic<Key,Value> Members 

    void IReadOnlyDic<Key, Value>.Add(Key key, Value value) 
    { 
     base.Add(key, value); 
    } 

    #endregion 
} 

per aggiungere elementi personalizzati;

IReadOnlyDic<int, int> dict = myDictInstance as IReadOnlyDic<int, int>; 
    if (dict != null) 
     dict.Add(1, 155); 
0

e questo è un altro modo

class ReadOnlyDic<Key, Value> : Dictionary<Key, Value> 
{ 
    private bool _locked = false; 

    public new void Add(Key key, Value value) 
    { 
     if (!_locked) 
     { 
      base.Add(key, value); 
     } 
     else 
     { 
      throw new ReadOnlyException(); 
     } 
    } 
    public void Lock() 
    { 
     _locked = true; 
    } 
} 
+0

+1 per la semplicità della soluzione e per la compatibilità con le interfacce del dizionario. Tuttavia: perché utilizzare "nuovo" anziché "sovrascrivere"? Inoltre, oltre all'Add, anche il metodo Remove dovrebbe essere sovrascritto. – chiccodoro

+0

@chiccodoro: 'Dictionary' non ha metodi' virtuali'. – SLaks

+0

perché è stato downvoted? - @SLaks: allright – chiccodoro

0

Mi è piaciuto il link da bruno-conde, che è stato uno più semplice, ma una volta non riesco a segnare il suo commento come la risposta, ti segnano Noldorin rispondi come ufficiale, perché è una risposta simile e soddisfacente. .

Peccato che non ci sia un modo per evitare che il codice da compilare :(Grazie, ragazzi

1

Esiste ora un modo per implementare una raccolta di tipo readonly statico alla classe. Ecco il mio codice:

private readonly Dictionary<int, string> percentageColour = new Dictionary<int, string>() 
{ 
    {40, "Red"}, 
    {70, "Yellow"}, 
    {101, "Green"} 
}; 

Speranza che aiuta.

+0

Dovrebbe essere la risposta con .net 4.5 per anni – Glenn

+0

Perché i downvotes dopo tutto questo tempo? :( –