I'm returning a reference to a dictionary in my read only property. How do I prevent consumers from changing my data? If this were an IList
I could simply return it AsReadOnly
. Is there something similar I can do with a dictionary?
Private _mydictionary As Dictionary(Of String, String)
Public ReadOnly Property MyDictionary() As Dictionary(Of String, String)
Get
Return _mydictionary
End Get
End Property
IsReadOnly on
IDictionary<TKey,TValue>
is inherited fromICollection<T>
(IDictionary<TKey,TValue>
extendsICollection<T>
asICollection<KeyValuePair<TKey,TValue>>
). It is not used or implemented in any way ( and is in fact "hidden" through the use of explicitly implementing the associatedICollection<T>
members ).There are at least 3 ways I can see to solve the problem:
IDictionary<TKey, TValue>
and wrap / delegate to an inner dictionary as has been suggestedICollection<KeyValuePair<TKey, TValue>>
set as read only or anIEnumerable<KeyValuePair<TKey, TValue>>
depending on the use of the value.ctor(IDictionary<TKey, TValue>)
and return a copy - that way the user is free to do with it as they please and it does not impact on the state of the object hosting the source dictionary. Note that if the dictionary you are cloning contains reference types ( not strings as shown in the example ) you will need to do the copying "manually" and clone the reference types as well.As an aside; when exposing collections, aim to expose the smallest possible interface - in the example case it should be IDictionary as this allows you to vary the underlying implementation without breaking the public contract that the type exposes.
No, but it would be easy to roll your own. IDictionary does define an IsReadOnly property. Just wrap a Dictionary and throw a NotSupportedException from the appropriate methods.
A read-only dictionary can to some extent be replaced by
Func<TKey, TValue>
- I usually use this in an API if I only want people performing lookups; it's simple, and in particular, it's simple to replace the backend should you ever wish to. It doesn't provide the list of keys, however; whether that matters depends on what you're doing.You could create a class that only implements a partial implementation of the dictionary, and hides all the add/remove/set functions.
Use a dictionary internally that the external class passes all requests to.
However, since your dictionary is likely holding reference types, there is no way you ca stop the user from setting values on the classes held by the dictionary (unless those classes themselves are read only)
Now, there are Microsoft Immutable Collections (
System.Collections.Immutable
). Get them via NuGet.It was announced in the recent BUILD conference that since .NET 4.5, the interface
System.Collections.Generic.IReadOnlyDictionary<TKey,TValue>
is included. The proof is here (Mono) and here (Microsoft) ;)Not sure if
ReadOnlyDictionary
is included too, but at least with the interface it shouldn't be difficult to create now an implementation which exposes an official .NET generic interface :)