Does C # have a way to give me an immutable dictionary?

Is there anything built into the core C # libraries that can give me an immutable dictionary?

Something in Java strings:

Collections.unmodifiableMap(myMap); 

And just to clarify, I do not want to stop the change of keys / values, namely the structure of the dictionary. I want something that will not succeed quickly and loudly if any of the IDictionary mutator methods is called ( Add, Remove, Clear ).

+66
java collections dictionary c #
Aug 29 '08 at 18:47
source share
13 answers

No, but the wrapper is pretty trivial:

 public class ReadOnlyDictionary<TKey, TValue> : IDictionary<TKey, TValue> { IDictionary<TKey, TValue> _dict; public ReadOnlyDictionary(IDictionary<TKey, TValue> backingDict) { _dict = backingDict; } public void Add(TKey key, TValue value) { throw new InvalidOperationException(); } public bool ContainsKey(TKey key) { return _dict.ContainsKey(key); } public ICollection<TKey> Keys { get { return _dict.Keys; } } public bool Remove(TKey key) { throw new InvalidOperationException(); } public bool TryGetValue(TKey key, out TValue value) { return _dict.TryGetValue(key, out value); } public ICollection<TValue> Values { get { return _dict.Values; } } public TValue this[TKey key] { get { return _dict[key]; } set { throw new InvalidOperationException(); } } public void Add(KeyValuePair<TKey, TValue> item) { throw new InvalidOperationException(); } public void Clear() { throw new InvalidOperationException(); } public bool Contains(KeyValuePair<TKey, TValue> item) { return _dict.Contains(item); } public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex) { _dict.CopyTo(array, arrayIndex); } public int Count { get { return _dict.Count; } } public bool IsReadOnly { get { return true; } } public bool Remove(KeyValuePair<TKey, TValue> item) { throw new InvalidOperationException(); } public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator() { return _dict.GetEnumerator(); } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return ((System.Collections.IEnumerable)_dict).GetEnumerator(); } } 

Obviously, you can change this installer [] above if you want to allow changing values.

+49
Aug 30 '08 at 3:56
source share

With the release of .NET 4.5, there is a new ReadOnlyDictionary class. You simply pass the IDictionary constructor to create an immutable dictionary.

Here is a useful extension method that you can use to simplify creating a dictionary for reading.

+14
Sep 17 '12 at 16:06
source share

I do not think so. There is a way to create a read-only and read-only list, but I don't think there is a built-in read-only dictionary. System.ServiceModel has an implementation of ReadOnlyDictinoary, but its internal one. It would probably not be easy to copy it using a Reflector, or just create your own from scratch. It basically wraps the dictionary and gives out when the mutator is called.

+3
Aug 29 '08 at 19:02
source share

Adding dbkk to the answer , I wanted to be able to use the object initializer when I first created my ReadOnlyDictionary. I made the following changes:

 private readonly int _finalCount; /// <summary> /// Takes a count of how many key-value pairs should be allowed. /// Dictionary can be modified to add up to that many pairs, but no /// pair can be modified or removed after it is added. Intended to be /// used with an object initializer. /// </summary> /// <param name="count"></param> public ReadOnlyDictionary(int count) { _dict = new SortedDictionary<TKey, TValue>(); _finalCount = count; } /// <summary> /// To allow object initializers, this will allow the dictionary to be /// added onto up to a certain number, specifically the count set in /// one of the constructors. /// </summary> /// <param name="key"></param> /// <param name="value"></param> public void Add(TKey key, TValue value) { if (_dict.Keys.Count < _finalCount) { _dict.Add(key, value); } else { throw new InvalidOperationException( "Cannot add pair <" + key + ", " + value + "> because " + "maximum final count " + _finalCount + " has been reached" ); } } 

Now I can use the class as follows:

 ReadOnlyDictionary<string, string> Fields = new ReadOnlyDictionary<string, string>(2) { {"hey", "now"}, {"you", "there"} }; 
+3
Jul 09 '09 at 15:33
source share

The open source PowerCollections library includes a read-only dictionary shell (as well as a read-only shell for almost everything else), accessible using the static ReadOnly() method of the Algorithms class.

+3
Jun 24 2018-11-11T00:
source share

One workaround may be to drop a new KeyValuePair list from the Dictionary to keep the original unmodified.

 var dict = new Dictionary<string, string>(); dict.Add("Hello", "World"); dict.Add("The", "Quick"); dict.Add("Brown", "Fox"); var dictCopy = dict.Select( item => new KeyValuePair<string, string>(item.Key, item.Value)); // returns dictCopy; 

Thus, the original dictionary will not be changed.

+2
Aug 29 '08 at 19:44
source share

Out of the box there is no way to do this. You can create it by deriving your own Dictionary class and introducing the necessary restrictions.

+1
Aug 29 '08 at 19:24
source share

I found the Inmutable (not READONLY) implementation of the AVLTree implementation for C # here.

The AVL tree has a logarithmic (not constant) cost for each operation, but it is motionless.

http://csharpfeeds.com/post/7512/Immutability_in_Csharp_Part_Nine_Academic_Plus_my_AVL_tree_implementation.aspx

+1
Feb 02 '09 at 14:21
source share

Since Linq there is a common ILookup interface. More details on MSDN .

Therefore, to simply get an immutable dictionary, you can call:

 using System.Linq; // (...) var dictionary = new Dictionary<string, object>(); // (...) var read_only = dictionary.ToLookup(kv => kv.Key, kv => kv.Value); 
+1
Sep 15 '09 at 17:49
source share

You can try something like this:

 private readonly Dictionary<string, string> _someDictionary; public IEnumerable<KeyValuePair<string, string>> SomeDictionary { get { return _someDictionary; } } 

This will eliminate the variability issue in favor of your caller either converting it to their dictionary:

 foo.SomeDictionary.ToDictionary(kvp => kvp.Key); 

... or use a comparison operation on a key rather than an index search, for example:

 foo.SomeDictionary.First(kvp => kvp.Key == "SomeKey"); 
0
Dec 21 2018-11-12T00:
source share

In general, it is much better not to miss a single dictionary in the first place (if you DO NOT HAVE).

Instead, create a domain object with an interface that does not offer any methods to modify the dictionary (which it wraps). Instead, the required LookUp method is proposed, which extracts an element from the dictionary by key (a bonus makes it easier to use than a dictionary).

 public interface IMyDomainObjectDictionary { IMyDomainObject GetMyDomainObject(string key); } internal class MyDomainObjectDictionary : IMyDomainObjectDictionary { public IDictionary<string, IMyDomainObject> _myDictionary { get; set; } public IMyDomainObject GetMyDomainObject(string key) {.._myDictionary .TryGetValue..etc...}; } 
0
Oct. 15 '13 at 17:45
source share

There is also another alternative there, as I described in:

http://www.softwarerockstar.com/2010/10/readonlydictionary-tkey-tvalue/

This is essentially a subclass of ReadOnlyCollection>, which does the job more elegantly. Elegant in the sense that it has compile-time support for creating a read-only dictionary, and not for eliminating exceptions from methods that modify elements inside it.

-one
Oct 30 '10 at 5:29
source share



All Articles