константный словарь в С#
-
21-08-2019 - |
Вопрос
У меня есть класс на 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, кто-то сможет «невинно» создать метод, который добавит ключ или удалит другой.Я хочу, чтобы люди смотрели и знали, что им не следует каким-либо образом менять словарь.Точно так же, как у меня с константной переменной.
Решение
В .NET Framework нет ничего, что могло бы вам помочь, но эта почта дает довольно хорошую реализацию общего ReadOnlyDictionary
в С#.Он реализует все интерфейсы, которые вы можете ожидать (IDictionary
, ICollection
, IEnumerable
, и т. д.), и в качестве бонуса весь класс и его члены полностью прокомментированы XML.
(Я воздержался от публикации кода здесь, потому что он действительно очень длинный со всеми комментариями XML.)
Другие советы
Полностью скройте словарь.Просто предоставьте метод 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];
}
}
Эх...тогда не определяйте метод добавления...
Держать myDictionary
приватную переменную и выставьте Getter/Indexer, чтобы ее можно было читать только снаружи этого класса.
задается вопросом, не упускает ли он суть
Нет встроенного способа сделать это, рассмотрите возможность использования класс-оболочка.
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);
и это другой способ
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;
}
}
Мне понравилось связь от Брюно-Конде, который был проще, но раз я не смогу пометить его комментарий как ответ, я отмечу Нолдорин ответьте как официальный, потому что это аналогичный и удовлетворительный ответ.
Жаль, что нет способа предотвратить компиляцию кода :(.Спасибо ребята
Вот лучшая альтернатива, как я описал:
http://www.softwarerockstar.com/2010/10/..
По сути, это гораздо более простое решение, создающее подкласс ReadOnlyCollection, которое выполняет работу более элегантно.
К вашему сведению, теперь он встроен в .net 4.5.
http://msdn.microsoft.com/en-us/library/gg712875(v=vs.110).aspx