I have a Dictionary
and would like to expose the member as read only. I see that I can return it as a IReadOnlyDictionar
I run into the same problem. I solved it on the following way.
List<string> list = new List<string>();
Dictionary<string, IReadOnlyCollection<string>> dic = new Dictionary<string, IReadOnlyCollection<string>>();
IReadOnlyDictionary<string, IReadOnlyCollection<string>> dicRo = new ReadOnlyDictionary<string, IReadOnlyCollection<string>>(dic);
list.Add("Test1");
dic["T"] = list.AsReadOnly();
ist.Add("Test2");
This has the positiv effekt, that you
Maybe this will help someone.
Given the fact that you're specifically looking for a read-only Dictionary<string, List<string>>
, you're basically looking exactly for a Lookup.
The Dictionary object has a ToLookup()
extension.
If you want to return a read only dictionary but still be able to mutate the dictionary and list in your class you could use casting to get back the list type.
This example is a bit contrived, but shows how it could work.
public class MyClass
{
Dictionary<string, IReadOnlyList<string>> _dictionary;
public IReadOnlyDictionary<string, IReadOnlyList<string>> Dictionary { get { return _dictionary; } }
public MyClass()
{
_dictionary = new Dictionary<string, IReadOnlyList<string>>();
}
public void AddItem(string item)
{
IReadOnlyList<string> readOnlyList = null;
List<string> list = null;
if (!_dictionary.TryGetValue(item, out readOnlyList))
{
list = new List<string>();
_dictionary.Add(item, list);
}
else
list = readOnlyList as List<string>;
list.Add(item);
}
}
If you goal is to have the property be immutable, then using a ReadOnlyDictionary would be the best option.
First, you'll have to create a new dictionary with the desired content types:
var dicWithReadOnlyList = dic.ToDictionary(
kv => kv.Key,
kv => kv.Value.AsReadOnly());
Then you can just return the new dictionary, since IReadOnlyDictionary
is a supertype of Dictionary
.
Why do you need to do that? Because Dictionary<T, A>
is not a supertype of Dictionary<T, B>
, even if A
is a supertype of B
. Why? Consider the following example:
var dic = new Dictionary<T, B>();
Dictionary<T, A> dic2 = dic; // Imagine this were possible...
dic2.Add(someT, someA); // ...then we'd have a type violation here, since
// dic2 = dic requires some B as the value.
In other words, TValue
in Dictionary
is not covariant. From an object-orientied point of view, covariance should be possible in the read-only version of the dictionary, but there are legacy issues in the .NET framework which prevent this (see the part starting with "UPDATE" in this question for details).
It would be as easy as casting the whole dictionary reference to IReadOnlyDictionary<string, IReadOnlyList<string>>
because Dictionary<TKey, TValue>
implements IReadOnlyDictionary<TKey, TValue>
.
BTW, you can't do that because you want the List<string>
values as IReadOnlyList<string>
.
So you need something like this:
var readOnlyDict = (IReadOnlyDictionary<string, IReadOnlyList<string>>)dict.ToDictionary(pair => pair.Key, pair => pair.Value.AsReadOnly());
This is just a suggestion, but if you're looking for immutable dictionaries, add System.Collections.Immutable NuGet package to your solution and you'll be able to use them:
// ImmutableDictionary<string, ImmutableList<string>>
var immutableDict = dict.ToImmutableDictionary(pair => pair.Key, pair => pair.Value.ToImmutableList());
Learn more about Immutable Collections here.
https://msdn.microsoft.com/en-us/library/acdd6hb7.aspx
You can use this to expose the object as readonly.
You could also use properties get; set; and only allow the get to be public.
But Matias answer seems to be more fitting.