To złe rozwiązanie, patrz na dole.
Dla tych, którzy nadal używają .NET 4.0 lub starszego, mam klasę, która działa tak jak ta w zaakceptowanej odpowiedzi, ale jest znacznie krótsza. Rozszerza istniejący obiekt Dictionary, przesłaniając (faktycznie ukrywając) niektórych członków, aby rzucali wyjątek po wywołaniu.
Jeśli obiekt wywołujący spróbuje wywołać Dodaj, Usuń lub inną operację mutacji, którą ma wbudowany słownik, kompilator zgłosi błąd. Używam atrybutów Przestarzałe, aby podnieść te błędy kompilatora. W ten sposób możesz zastąpić słownik tym ReadOnlyDictionary i natychmiast zobaczyć, gdzie mogą wystąpić problemy, bez konieczności uruchamiania aplikacji i czekania na wyjątki w czasie wykonywania.
Spójrz:
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) { }
[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(); }
public new TValue this[TKey key]
{
get { return base[key]; }
}
[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(); }
}
W tym rozwiązaniu występuje problem wskazany przez @supercat przedstawiony tutaj:
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);
}
Zamiast podawać błąd w czasie kompilacji, jak się spodziewałem, lub wyjątek czasu wykonania, taki jak miałem nadzieję, ten kod działa bez błędów. Drukuje cztery liczby. To sprawia, że mój ReadOnlyDictionary jest ReadWriteDictionary.