Yes! For people doing custom implementation to create a Read Only Dictionary, there is now a .NET BCL implementation of the same in .NET 4.5.
For the Uninitiated the question is - Why do you need a ReadOnlyDictionary in the first place?
A ReadOnlyDictionary is a useful data container when you are sending data across layers of an application and you want to ensure the data is not modified across the layer.
A good use case for this is Configuration information that is critical for functioning of an application. We may want multiple layers of the application to have access to the configuration information (and a dictionary is a very good way to pass configuration around) but no one should be able to update the configuration directly without going through the required checks and balances. In the following sample, we will look a small such sample.
A Read-only Configuration
Step 1: Create a new Console Application in Visual Studio 2012 CP. Name the Solution ‘ReadOnlyCollectionSample’.
Step 2: Add two Window Class Library projects, ConfigurationLibrary and ConfigurationConsumer.
Step 3: In the ConfigurationLibrary project, add a Class called ConfigurationContainer
Step 4: Setting up the ConfigurationContainer
- In the ConfigurationContainer, add a field _mutableConfiguration for type Dictionary<string, string>. This is where we will load our configuration.
- In the constructor, initialize the _mutableConfiguration dictionary and add some key value pairs to it.
- Add a property called Configuration with the type ReadOnlyDictionary<string, string> with a getter only. The Getter will return a new instance of ReadOnlyDictionary<string, string>. The Read Only Dictionary is initiated using the _mutableConfiguration.
- Add a public method AddToConfiguration(key, value). This method will add/update a configuration key/value pairs from outside.
- Add a method ConfigurationAllowed that returns a Boolean. This contains the logic that decides if a particular configuration parameter can be updated or not and update it accordingly. Essentially we have restricted users from updated the Configuration and we will be controlling the update via this method.
- The final class looks as follows:
Step 5: Setting up the ConfigurationConsumer
- Rename the Class1 to ConfigurationConsumer
- Declare a field of type IReadOnlyDictionary<string, string> called _config.
- In the Constructor initialize the _config field by using the Configuration property of an instance of ConfigurationContainer
- Add a method DoSomething() that checks if a “key” called configuration exists and prints a message with the value if it does. If the “key” does not exist it prints a different message.
- Add another method called BeNaughtyWithConfiguration(). Try to cast the _config read-only dictionary into an ordinary IDictionary. Now add a key to the IDictionary instance. The full listing is as follows
Step 6: Using the Configuration in ReadOnlyCollectionSample
- In the Program.cs’ main method instantiate the ConfigurationConsumer and call the DoSomething() method
- Add a Console.ReadLine() to wait for user input before executing the next line.
- Call the BeNaughtyWithConfiguration() method
- The Final code is as follows
Running the Sample
Build and run the sample. The output on the console will be something as follows:
As we see, the value from the Read only dictionary was extracted successfully.
Next we hit enter and the code tries to execute the BeNaughtyWithConfiguration method. Wham! We get the following exception:
As we can see, our ReadOnly configurations are safe from type conversion into updatable counterparts.
If you add a watch for the convertToReadWrite.IsReadOnly property, you will find it to be ‘True’.
A Note about Dictionary of Mutable Objects
In our above sample, the Dictionary was that of primitive type ‘string’ that is itself immutable. However if you had a read only dictionary of type say ConfigElement, where ConfigElement is defined as follows:
The ReadOnlyDictionary in this case would not be able to prevent changes to the ConfigElement instance. So if someone retrieved the ConfigElement from the readonly dictionary and updated the Value property, the property would get change in the instance that’s in the Dictionary.
This code will give us the following output
As we can see the element got updated in the Dictionary.
To conclude, the new ReadOnlyDictionary<T,T> generic type in .NET 4.5 fulfills a long standing feature request for the BCL. It will be very useful for scenarios where read only Dictionaries need to be exposed. One such case is shown above.
The final code (including use of the ConfigElement type) is available here. Repo at: https://github.com/devcurry/ReadOnlyCollectionSample
Note: We have tested the code on the following combinations
1. VS 2012 RC + Windows 7
2. Win8 CP with VS11 Beta to run the code sample. It is going to work on Win8 RP + VS 2012 RC as well.