Это плохое решение, смотрите внизу.
Для тех, кто все еще использует .NET 4.0 или более раннюю версию, у меня есть класс, который работает так же, как и в принятом ответе, но он намного короче. Он расширяет существующий объект Dictionary, переопределяя (фактически скрывая) определенные члены, чтобы они вызывали исключение при вызове.
Если вызывающая сторона пытается вызвать Add, Remove или какую-либо другую мутирующую операцию, имеющуюся во встроенном словаре, компилятор выдаст ошибку. Я использую устаревшие атрибуты, чтобы вызвать эти ошибки компилятора. Таким образом, вы можете заменить Dictionary на этот ReadOnlyDictionary и сразу увидеть, где могут быть какие-либо проблемы, без необходимости запуска приложения и ожидания исключений во время выполнения.
Взглянуть:
public class ReadOnlyException : Exception
{
}
public class ReadOnlyDictionary<TKey, TValue> : Dictionary<TKey, TValue>
{
public ReadOnlyDictionary(IDictionary<TKey, TValue> dictionary)
: base(dictionary) { }
public ReadOnlyDictionary(IDictionary<TKey, TValue> dictionary, IEqualityComparer<TKey> comparer)
: base(dictionary, comparer) { }
//The following four constructors don't make sense for a read-only dictionary
[Obsolete("Not Supported for ReadOnlyDictionaries", true)]
public ReadOnlyDictionary() { throw new ReadOnlyException(); }
[Obsolete("Not Supported for ReadOnlyDictionaries", true)]
public ReadOnlyDictionary(IEqualityComparer<TKey> comparer) { throw new ReadOnlyException(); }
[Obsolete("Not Supported for ReadOnlyDictionaries", true)]
public ReadOnlyDictionary(int capacity) { throw new ReadOnlyException(); }
[Obsolete("Not Supported for ReadOnlyDictionaries", true)]
public ReadOnlyDictionary(int capacity, IEqualityComparer<TKey> comparer) { throw new ReadOnlyException(); }
//Use hiding to override the behavior of the following four members
public new TValue this[TKey key]
{
get { return base[key]; }
//The lack of a set accessor hides the Dictionary.this[] setter
}
[Obsolete("Not Supported for ReadOnlyDictionaries", true)]
public new void Add(TKey key, TValue value) { throw new ReadOnlyException(); }
[Obsolete("Not Supported for ReadOnlyDictionaries", true)]
public new void Clear() { throw new ReadOnlyException(); }
[Obsolete("Not Supported for ReadOnlyDictionaries", true)]
public new bool Remove(TKey key) { throw new ReadOnlyException(); }
}
У этого решения есть проблема, указанная @supercat, показанной здесь:
var dict = new Dictionary<int, string>
{
{ 1, "one" },
{ 2, "two" },
{ 3, "three" },
};
var rodict = new ReadOnlyDictionary<int, string>(dict);
var rwdict = rodict as Dictionary<int, string>;
rwdict.Add(4, "four");
foreach (var item in rodict)
{
Console.WriteLine("{0}, {1}", item.Key, item.Value);
}
Вместо того, чтобы выдавать ошибку времени компиляции, как я ожидал, или исключение времени выполнения, как я надеялся, этот код выполняется без ошибок. Он печатает четыре номера. Это делает мой ReadOnlyDictionary ReadWriteDictionary.