Make dictionary read only in C#

陌路散爱 提交于 2019-11-28 03:06:35

问题


I have a Dictionary<string, List<string>> and would like to expose the member as read only. I see that I can return it as a IReadOnlyDictionary<string, List<string>>, but I can't figure out how to return it as an IReadOnlyDictionary<string, IReadOnlyList<string>>.

Is there a way to do this? In c++ I'd just be using const, but C# doesn't have that.

Note that simply using a IReadOnlyDictionary does not help in this case, because I want the values to be read only as well. It appears the only way to do this is build another IReadOnlyDictionary, and add IReadOnlyList to them.

Another option, which I wouldn't be thrilled with, would be to create wrapper which implements the interface IReadOnlyDictionary>, and have it hold a copy of the original instance, but that seems overkill.


回答1:


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());

Immutable dictionaries

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.




回答2:


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.




回答3:


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).




回答4:


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.




回答5:


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.



来源:https://stackoverflow.com/questions/39086520/make-dictionary-read-only-in-c-sharp

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!