2009-05-12 19 views
8

Tengo una clase en C# que contiene un diccionario, que quiero crear y asegurar que nada se agregue, edite o elimine de este diccionario mientras exista la clase que lo contiene.Diccionario const en C#

Readonly realmente no ayuda, una vez que probé y vi que puedo agregar elementos después. Solo por ejemplo, creé un ejemplo:

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

} 

Quiero que el método Agregar no funcione. Si es posible, quiero que ni siquiera compile. ¿Alguna sugerencia?

En realidad, me preocupa que el código esté abierto para muchas personas. Entonces, incluso si oculto el método Agregar, será posible que alguien cree "inocentemente" un método que agregue una clave, o elimine otra. Quiero que las personas miren y sepan que no deberían cambiar el diccionario de ninguna manera. Justo como tengo con una variable const.

+2

Los requisitos extraños sugieren que su diseño tiene problemas. Es posible que desee volver a pensar lo que está intentando aquí. De lo contrario, puede crear fácilmente su propia implementación que hace esto. – Will

+3

Puede implementar su propio diccionario. Pregunta similar: http://stackoverflow.com/questions/35002/does-c-have-a-way-of-giving-me-an-immutable-dictionary –

Respuesta

12

No hay nada en el .NET Framework para ayudarle a cabo aquí, pero this post da una muy buena aplicación de un genérico ReadOnlyDictionary en C# . Implementa todas las interfaces que podría esperar (IDictionary, ICollection, IEnumerable, etc.) y como beneficio adicional, toda la clase y sus miembros se comentan completamente con XML.

(he abstuvieron de publicar el código aquí, porque en realidad es bastante largo con todos los comentarios XML.)

+3

+1 para "no publicar el código aquí"! Vincular a la fuente original siempre es mejor; similar a acreditar al autor. – Cerebrus

+3

@Cerebrus: Sí, siempre se debe vincular primero a la fuente original; como dices, lo mejor es atribuírselo al autor. Mi opinión es que si el código/texto es lo suficientemente corto, generalmente es útil * reflejar * aquí (en caso de que el sitio se caiga por ejemplo), pero eso no es realmente apropiado en este caso. – Noldorin

+1

Gracias por hacer referencia a mi artículo :-). – Steven

3

Eh ... entonces no definen el método Add ...

Mantenga el myDictionary variable privada y exponer un captador/controlador paso a paso de forma que sólo se puede leer desde fuera esa clase ..

se pregunta si le falta por completo el punto

7

Ocultar el diccionario totalmente. Solo proporcione un método get en la clase DictContainer que recupera elementos del diccionario.

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 
} 

para añadir elementos personalizados;

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

y esta es otra manera

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 por la simplicidad de la solución y por la compatibilidad con las interfaces del diccionario. Sin embargo: ¿Por qué usar "nuevo" en lugar de "sobrescribir"? Además, además del Add, el método Remove debe ser anulado también. – chiccodoro

+0

@chiccodoro: 'Dictionary' no tiene métodos' virtuales'. – SLaks

+0

¿por qué se bajó este voto? - @SLaks: allright – chiccodoro

0

Me gustó la link de bruno-conde, que era uno más sencillo, pero una vez que no puedo marcar su comentario como la respuesta, voy a marcar Noldorin responde como el oficial, ya que es una respuesta similar y satisfactoria. .

Lástima que no hay una manera de prevenir el código de compilación :(Gracias, chicos

1

Ahora hay una forma de implementar una colección de solo lectura que es estática para la clase. Aquí está mi código:

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

Espero que ayude.

+0

Ahora debería ser la respuesta con .net 4.5 fuera por años – Glenn

+0

¿Por qué los downvotes después de todo este tiempo? :( –