Je retourne une référence à un dictionnaire dans ma propriété en lecture seule. Comment prévenir les consommateurs de modifier mes données ? Si c’était un je pourrais simplement le retourner
. Y a-t-il quelque chose de similaire, que je peux faire avec un dictionnaire ?
Réponses
Trop de publicités?.NET 4.5
L' .NET Framework 4.5 BCL introduit ReadOnlyDictionary<TKey, TValue>
(source).
Comme l' .NET Framework 4.5 BCL ne comprend pas d' AsReadOnly
pour les dictionnaires, vous aurez besoin d'écrire votre propre (si vous le voulez). Il serait quelque chose comme ce qui suit, la simplicité de ce qui peut-être explique pourquoi ce n'était pas une priorité pour .NET 4.5.
public static ReadOnlyDictionary<TKey, TValue> AsReadOnly<TKey, TValue>(
this IDictionary<TKey, TValue> dictionary)
{
return new ReadOnlyDictionary<TKey, TValue>(dictionary);
}
.NET 4.0 et ci-dessous
Avant .NET 4.5, il n'est pas .NET framework classe qui encapsule une Dictionary<TKey, TValue>
comme le ReadOnlyCollection enroule une Liste. Cependant, il n'est pas difficile d'en créer un.
Voici un exemple - il y a beaucoup d'autres si vous Google pour ReadOnlyDictionary.
Il a été annoncé lors de la récente conférence BUILD qui depuis .NET 4.5, l'interface System.Collections.Generic.IReadOnlyDictionary<TKey,TValue>
est inclus. La preuve en est ici (Mono) et ici (Microsoft) ;)
Vous ne savez pas si ReadOnlyDictionary
est incluse trop, mais au moins avec l'interface, il ne devrait pas être difficile de créer maintenant une mise en œuvre qui expose un officiel .NET interface générique :)
N’hésitez pas à utiliser mon wrapper simple. Il n’implémente pas de IDictionary, donc il ne doit pas lever d’exceptions lors de l’exécution pour les méthodes de dictionnaire qui allait changer le dictionnaire. Méthodes de changement tout simplement ne sont pas là. J’ai fait mon propre interface pour qu’on appelle IReadOnlyDictionary.
IsReadOnly sur IDictionary<TKey,TValue>
est hérité de l' ICollection<T>
(IDictionary<TKey,TValue>
s'étend ICollection<T>
comme ICollection<KeyValuePair<TKey,TValue>>
). Il n'est pas utilisé ou mis en œuvre dans tous les sens ( et est en fait "caché" par le biais de l'utilisation de explicitement la mise en œuvre de la associée ICollection<T>
des membres ).
Il y a au moins 3 façons je peux voir à résoudre le problème:
- Mettre en œuvre une coutume de lire
seulement
IDictionary<TKey, TValue>
et wrap / déléguer à un intérieur dictionnaire comme cela a été suggéré - De retour d'un
ICollection<KeyValuePair<TKey, TValue>>
en lecture seule ou unIEnumerable<KeyValuePair<TKey, TValue>>
selon l'utilisation de la valeur - Clone le dictionnaire à l'aide de la copie
constructeur
.ctor(IDictionary<TKey, TValue>)
et retourner une copie qui façon dont l'utilisateur est libre d'en faire ce comme ils s'il vous plaît et il n'a pas impact sur l'état de l'objet l'hébergement du dictionnaire source. Note que si le dictionnaire le clonage contient les types de référence ( pas de chaînes comme indiqué dans l'exemple ) vous aurez besoin de faire la copie "manuellement", et le clone de référence types ainsi.
Comme un de côté; quand on expose des collections, ont pour objectif d'exposer le plus possible à l'interface dans le cas de l'exemple, il devrait être IDictionary que cela vous permet de varier l'implémentation sous-jacente sans rompre le contrat public que le type expose.