将嵌套字典转换为 IReadOnlyDictionary

Sor*_*ors 3 c# collections dictionary readonly .net-4.5

我试图给出IReadOnly对内部Collection对象的引用。这在大多数情况下效果很好,但如果我想将包含集合的字典转换为IReadOnlyDictionary包含IReadOnlyCollection.

这是一个代码示例:

    var list = new List<int>();
    IReadOnlyList<int> listReference = list; //works;

    var dictionary = new Dictionary<int, int>();
    IReadOnlyDictionary<int, int> dictionaryReference = dictionary; //works

    var nestedList = new List<List<int>>();
    IReadOnlyList<IReadOnlyList<int>> nestedReadOnlyListReference = nestedList; //works

    var nestedDictionary = new Dictionary<int, List<int>>();
    //IReadOnlyDictionary<int, IReadOnlyList<int>> nestedReadOnlyDictionaryReference = nestedDictionary; //does not work, can not implicitly convert

    //current workaround
    var nestedDictionaryReferenceHelper = new Dictionary<int, IReadOnlyList<int>>();
    foreach (var kvpNestedDictionary in nestedDictionary)
    {
        nestedDictionaryReferenceHelper.Add(kvpNestedDictionary.Key, (IReadOnlyList<int>)kvpNestedDictionary.Value);
    }
    IReadOnlyDictionary<int, IReadOnlyList<int>> nestedReadOnlyDictionaryReference = nestedDictionaryReferenceHelper; //works, but is only a reference to the internal List, not to the dictionary itself
Run Code Online (Sandbox Code Playgroud)

解决方法非常难看,因为它需要额外的内存,并且每次nestedDictionary更改值时都需要手动更新。

有什么简单的方法可以转换这样的嵌套字典吗?

Phi*_*ard 6

在这个 SO question 中,您可以找到一个很好的解释为什么不支持强制转换字典值。请参阅 Eric Lippert 已接受的答案。

虽然我不推荐这样做,但您可以使用以下 LINQ 表达式将字典的值转换为只读列表:

IReadOnlyDictionary<int, IReadOnlyList<int>> nestedReadOnlyDictionaryReference = nestedDictionary.ToDictionary(kv => kv.Key, kv => kv.Value as IReadOnlyList<int>);
Run Code Online (Sandbox Code Playgroud)

它是您的解决方法的较短版本,并且是惰性评估的,但由于以下原因,我不建议这样做:

  1. 此解决方案仍会创建字典的副本,并且不会更新原始字典中的任何新条目/已删除条目。
  2. 字典的值,即只读列表,指的是原始列表和字典中只读版本中更新的更改。

这是不一致的行为,因此是一种不好的做法!

除非不可能转换字典的值,否则我不建议这样做。您应该深度复制包括嵌套列表在内的整个字典,或者使用其他支持强制转换的容器。