C'est une mauvaise solution, voir en bas.
Pour ceux qui utilisent encore .NET 4.0 ou une version antérieure, j'ai une classe qui fonctionne exactement comme celle de la réponse acceptée, mais elle est beaucoup plus courte. Il étend l'objet Dictionary existant, remplaçant (masquant en fait) certains membres pour qu'ils lèvent une exception lorsqu'ils sont appelés.
Si l'appelant essaie d'appeler Add, Remove ou une autre opération de mutation du dictionnaire intégré, le compilateur lèvera une erreur. J'utilise les attributs obsolètes pour signaler ces erreurs de compilation. De cette façon, vous pouvez remplacer un dictionnaire par ce ReadOnlyDictionary et voir immédiatement où peuvent se trouver les problèmes sans avoir à exécuter votre application et à attendre les exceptions d'exécution.
Regarde:
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(); }
}
Cette solution a un problème signalé par @supercat illustré ici:
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);
}
Plutôt que de donner une erreur de compilation comme je m'y attendais, ou une exception d'exécution comme je l'espérais, ce code s'exécute sans erreur. Il imprime quatre nombres. Cela fait de mon ReadOnlyDictionary un ReadWriteDictionary.