我有一个Dictionary<string, List<string>>
,并希望将该成员公开为只读。我看到我可以将其作为IReadOnlyDictionary<string, List<string>>
返回,但我无法弄清楚如何将其作为IReadOnlyDictionary<string, IReadOnlyList<string>>
返回。
有办法做到这一点吗?在c ++中,我只是使用const,但C#没有。
请注意,在这种情况下简单地使用IReadOnlyDictionary
没有帮助,因为我希望只读取值。似乎唯一的方法是构建另一个IReadOnlyDictionary,并向它们添加IReadOnlyList。
我不会兴奋的另一个选择是创建实现接口IReadOnlyDictionary&gt;的包装器,并让它保存原始实例的副本,但这似乎有点过分了。
答案 0 :(得分:13)
将整个字典引用转换为IReadOnlyDictionary<string, IReadOnlyList<string>>
就好了,因为Dictionary<TKey, TValue>
实现了IReadOnlyDictionary<TKey, TValue>
。
顺便说一句,你不能这样做,因为你希望List<string>
值为IReadOnlyList<string>
。
所以你需要这样的东西:
var readOnlyDict = (IReadOnlyDictionary<string, IReadOnlyList<string>>)dict.ToDictionary(pair => pair.Key, pair => pair.Value.AsReadOnly());
这只是一个建议,但如果您正在寻找不可变词典,请将System.Collections.Immutable
NuGet package添加到您的解决方案中,然后您就可以使用它们了:
// ImmutableDictionary<string, ImmutableList<string>>
var immutableDict = dict.ToImmutableDictionary(pair => pair.Key, pair => pair.Value.ToImmutableList());
答案 1 :(得分:3)
鉴于您专门寻找只读Dictionary<string, List<string>>
这一事实,您基本上正在寻找Lookup。
Dictionary对象的扩展名为ToLookup()
。
答案 2 :(得分:1)
首先,您必须创建一个包含所需内容类型的新词典:
var dicWithReadOnlyList = dic.ToDictionary(
kv => kv.Key,
kv => kv.Value.AsReadOnly());
然后您可以返回新词典,因为IReadOnlyDictionary
是Dictionary
的超类型。
为什么你需要这样做?因为Dictionary<T, A>
不是Dictionary<T, B>
的超类型,所以即使 A
是B
的超类型。为什么?请考虑以下示例:
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.
换句话说,TValue
is not covariant中的Dictionary
。从面向对象的角度来看,协方差应该在字典的只读版本中是可能的,但是在.NET框架中存在遗留问题阻止了这一点(参见以“更新“this question以获取详细信息。”
答案 3 :(得分:1)
我遇到了同样的问题。我通过以下方式解决了它。
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");
具有正向效果,即您
也许这会帮助某人。
答案 4 :(得分:0)
如果您想要返回一个只读字典,但仍然能够改变您的类中的字典和列表,您可以使用强制转换来获取列表类型。
这个例子有点人为,但展示了它是如何工作的。
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);
}
}
如果您的目标是使属性不可变,那么使用ReadOnlyDictionary将是最佳选择。
答案 5 :(得分:-1)
https://msdn.microsoft.com/en-us/library/acdd6hb7.aspx
您可以使用它将对象公开为只读。
你也可以使用属性get;组;并且只允许公开。
但Matias的答案似乎更合适。