如何从IReadOnlyDictionary <,>创建一个新的Dictionary <,>?

Dan*_*olf 17 c# dictionary

.NET 4.5引入了方便的IReadOnlyDictionary<TKey, TValue>界面.A Dictionary<TKey, TValue> 是一个 IReadOnlyDictionary<TKey, TValue>,所以我可以通过前者而不需要后者.

但我不确定相反的方式:如何Dictionary<,>基于现有创建新的IReadOnlyDictionary<,>

  • Dictionary<,>有几个构造函数采取IDictionary<,>- 但没有采取IReadOnlyDictionary<,>.
  • IReadOnlyDictionary<,>有一个扩展方法ToDictionary<,>().但是,这是继承自IEnumerable<>.因此,要使用它,我必须通过两项完全冗余的代表是这样的:readOnlyDict.ToDictionary(pair => pair.Key, pair => pair.Value).丑陋!
  • 当然,我总是可以创建一个新的Dictionary<,>,迭代原始对并复制它们.

在我看来,应该有一个微不足道的方法来创建一个Dictionary<,>基于现有的新IReadOnlyDictionary<,>.我错过了什么吗?

编辑:一些澄清.我不是在寻找治疗的一些神奇的方法IReadOnlyDictionary<,>Dictionary<,>.我想创建一个Dictionary<,>从a 复制其初始值的new IReadOnlyDictionary<,>.这个问题是一个冗长的问题:

Dictionary<,>有一个方便的构造函数来复制一个初始值IDictionary<,>.为什么没有一个人拿出一个IReadOnlyDictionary<,>什么是实现相同结果的最惯用的方法呢?

Pet*_*iho 12

Dictionary<TKey, TValue>能够实现IReadOnlyDictionary<TKey, TValue>,因为任何采用后者的代码都承诺不修改字典,字典是前者提供的功能的子集.

但考虑另一个方向.你从一开始IReadOnlyDictionary<TKey, TValue>,然后尝试将其变成常规Dictionary<TKey, TValue>.现在,你已经采取了以前承诺不被修改的东西,并把它变成可以修改的东西.

显然,这是不会做的.

此外,您不能只假设只读实现会在修改时抛出异常或某些东西(例如运行时安全,即使不是编译时安全),因为如您所知,您始终可以获得只读来自可变实现的接口.

所以为了安全起见,您有两种选择:

  1. 只需将整个字典内容复制到一个新对象中即可.
  2. 如果您尝试修改它IDictionary<TKey, TValue>,将该只读对象包装在引发异常的实现中.

请注意,后者实际上并没有为您提供您特别要求的内容.它很接近,但它不是一个真实的例子Dictionary<TKey, TValue>.

在复制方面,您有很多选择.就个人而言,我认为ToDictionary()本身就是好的.但如果你真的不喜欢详细程度,你可以用扩展方法包装它:

public static Dictionary<TKey, TValue> ToDictionary<TKey, TValue>(
    this IReadOnlyDictionary<TKey, TValue> dict)
{
    return dict.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
}
Run Code Online (Sandbox Code Playgroud)


附录:
在我看来,我应该澄清一下:以上都假设你试图转换一个任意的实例IReadOnlyDictionary<TKey, TValue>.显然,如果你知道或者至少怀疑你的IReadOnlyDictionary<TKey, TValue>对象实际上是一个实例Dictionary<TKey, TValue>,你可以直接投射或尝试(直接)投射Dictionary<TKey, TValue>.


Pab*_*o H 5

似乎是后来添加的,并且出于向后兼容性的原因,没有IReadOnlyDictionary<>对现有类(例如)进行改造以使用Dictionary<>方法支持它。[需要引用],不过。

就其价值而言, Microsoft 的构造函数的参考实现本质上是Dictionary

Dictionary(IDictionary dictionary)
: this(dictionary.Count) {
    foreach (KeyValuePair<TKey,TValue> pair in dictionary) {
            Add(pair.Key, pair.Value);
    }
}
Run Code Online (Sandbox Code Playgroud)

本质上Enumerable

Dictionary<> ToDictionary<>(this IEnumerable<> source, Func<> keySelector, Func<> elementSelector) 
{
    Dictionary<> d = new Dictionary<>();
    foreach (TSource element in source) 
    d.Add(keySelector(element), elementSelector(element));
    return d;
}
Run Code Online (Sandbox Code Playgroud)

所以差异似乎主要在于对选择器委托的调用。

因此,复制构造函数代码但采用 a 的扩展方法IReadOnlyDictionary<>,或多或少像 @Steve 所做的那样,似乎稍微简单一些,效率更高一些......


Ran*_*ans 5

你可以这样做:

Dictionary<string, string> dictionary = readOnlyDictionary
                .Select(dict => dict).ToDictionary(pair => pair.Key, pair => pair.Value);
Run Code Online (Sandbox Code Playgroud)