2009-05-12 7 views
8

У меня есть класс в C#, который содержит словарь, который я хочу создать и не гарантировать ничего, как добавленный, отредактированный или удаленный из этого словаря, если класс, который содержит его, существует.const Словарь в C#

readonly действительно не помогает, как только я протестировал и увидел, что я могу добавить элементы после. Например, я привел пример:

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

} 

Я хочу, чтобы метод Add не работал. Если возможно, я хочу, чтобы он даже не компилировался. Какие-либо предложения?

На самом деле, я беспокоюсь за то, что это код, который будет открыт для многих людей. Таким образом, даже если я скрою метод Add, кто-то сможет «невинно» создать метод, который добавит ключ, или удалить другой. Я хочу, чтобы люди смотрели и знали, что они не должны менять словарь каким-либо образом. Точно так же, как у меня есть переменная const.

+2

Странные требования предполагают, что у вашего дизайна есть проблемы. Возможно, вам захочется переосмыслить, что вы пытаетесь здесь сделать. В противном случае вы можете легко создать свою собственную реализацию, которая сделает это. – Will

+3

Вы можете реализовать свой собственный словарь. Аналогичный вопрос: http://stackoverflow.com/questions/35002/does-c-have-a-way-of-giving-me-an-immutable-dictionary –

ответ

12

Там нет ничего в .NET Framework, чтобы помочь вам здесь, но this post дает довольно хорошую реализацию общей ReadOnlyDictionary в C# , Он реализует все интерфейсы, которые вы могли бы ожидать (IDictionary, ICollection, IEnumerable и т. Д.), И в качестве бонуса весь класс и его члены полностью комментируются XML.

(я воздержался от размещения кода здесь, потому что это на самом деле довольно долго со всеми комментариями XML.)

+3

+1 для «не размещайте код здесь»! Связывание с исходным источником всегда лучше; сродни кредитованию автора. – Cerebrus

+3

@Cerebrus: Да, всегда нужно сначала ссылаться на исходный источник - как вы говорите, лучше всего приписать его автору. Мое мнение состоит в том, что если код/​​текст достаточно короткий, обычно полезно * mirror * здесь (в случае, если сайт идет вниз, например), но в этом случае это не очень удобно. – Noldorin

+1

Спасибо за ссылку на мою статью :-). – Steven

3

Эх ... тогда не определяет метод Add ...

Держите переменные частную myDictionary и выставить Getter/Индексатор так, что она может быть прочитана только из-за пределы этого класса ..

Чудеса, если он полностью отсутствует.

7

Скрыть словарь полностью. Просто дайте метод get в классе DictContainer, который извлекает элементы из словаря.

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

Там нет встроенного способа сделать это, рассмотреть вопрос об использовании a wrapper class.

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 
} 

для добавления пользовательских элементов;

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

и это еще один способ

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 для простоты решения и для совместимости с интерфейсами Dictionary. Однако: Зачем использовать «новый» вместо «переопределить»? Кроме того, кроме Add, метод Remove также должен быть переопределен. – chiccodoro

+0

@chiccodoro: 'Словарь' не имеет' виртуальных' методов. – SLaks

+0

почему это было downvoted? - @SLaks: allright – chiccodoro

0

мне понравилась link от bruno-conde, которая была более простой, но как только я не могу отметить его комментарий как ответ, я буду отмечать Noldorin ответьте как чиновник, потому что это аналогичный и удовлетворительный ответ. .

Жаль, что это не способ предотвратить код от компиляции :(Спасибо, ребята

0

Вот лучшая альтернатива, как я описал в:

http://www.softwarerockstar.com/2010/10/ ..

По сути, это гораздо проще подклассификация решений ReadOnlyCollection, которая делает работу более элегантной.

1

Теперь существует способ реализовать сборку readonly, статичную для класса. Вот мой код:

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

Надежда, что помогает.

+0

Должен теперь быть ответ с .net 4.5 out for years – Glenn

+0

Почему downvotes после всего этого времени? :( –