无法将 Dictionary<string, List<string>> 转换为 IReadOnlyDictionary<string, IReadOnlyCollect
Posted
技术标签:
【中文标题】无法将 Dictionary<string, List<string>> 转换为 IReadOnlyDictionary<string, IReadOnlyCollection<string>>【英文标题】:Can't convert Dictionary<string, List<string>> to IReadOnlyDictionary<string, IReadOnlyCollection<string>> 【发布时间】:2021-10-13 07:00:39 【问题描述】:谁能解释一下这个问题?
Dictionary<string, List<string>> x
= new Dictionary<string, List<string>>();
IReadOnlyDictionary<string, IReadOnlyCollection<string>> y
= new Dictionary<string, IReadOnlyCollection<string>>();
y = x; // CS0266: Cannot implicitly convert type...
【问题讨论】:
请始终显示您遇到的实际错误,这样更容易提供帮助。 Variance in C#. @JonSkeet 我应该知道最好不要在我献血几分钟后使用 SO :) @DavidG:IReadOnlyCollection<T>
并不意味着该集合是只读的,只是接口仅限于此。
这能回答你的问题吗? Cannot convert source type 'List<Person>' to IList<ISomething> 和 convert List<List<object>> to IList<IList<object>> 和 Convert IList<IList<object>> to List<List<object>> 和 still confused about covariance and contravariance & in/out 和 C# generic inheritance and covariance part 2
【参考方案1】:
您可以像这样接近您的目标:
Dictionary<string, List<string>> x = new Dictionary<string, List<string>>()
"Foo", new List<string> "A", "B", "C"
;
IReadOnlyDictionary<string, ReadOnlyCollection<string>> y =
new ReadOnlyDictionary<string, ReadOnlyCollection<string>>(x.ToDictionary(k => k.Key, v => new ReadOnlyCollection<string>(v.Value)));
IReadOnlyCollection<string> foo = y["Foo"];
请注意,ReadOnlyCollection<T>
包含您的原始列表。它不复制元素。 ReadOnlyDictionary<TKey, TValue>
也一样。
【讨论】:
【参考方案2】:IReadOnlyDictionary
的值不是covariant。这是为了围绕TryGetValue
方法提供类型安全。
考虑这个例子:
Dictionary<string, List<string>> x = new Dictionary<string, List<string>>
"Key", new List<string>()
;
IReadOnlyDictionary<string, IReadOnlyCollection<string>> y = new Dictionary<string, IReadOnlyCollection<string>>
"Key", new System.ArraySegment<string>() //This is allowed because an ArraySegment implements IReadOnlyCollection<string>
;
List<string> foo;
x.TryGetValue("Key", out foo);
foo.Add("Some string");
最后三行适用于x
,因为它的值是List<string>
。如果将y
分配给x
,它将不起作用,因为它的值不是List<string>
,并且您不能在其上调用Add
。这是行不通的:
y.TryGetValue("Key", out foo); //Error
这也不会:
x = y;
x.TryGetValue("Key", out foo); //Error
因为它适用于x
而不适用于y
,所以它们不是类型兼容的,因此不允许强制转换。
【讨论】:
【参考方案3】:这篇文章完美地描述了您在代码中遇到的情况。
Click?
Dictionary
但考虑另一个方向。您从 IReadOnlyDictionary
显然,那是行不通的。
此外,您不能只假设只读实现在修改时会抛出异常或某些东西(例如运行时安全,即使不是编译时安全),因为如您所知,您总是可以获得来自可变实现的只读接口。
为了安全起见,您有两种选择:
只需将整个字典内容复制到一个新对象中。
将只读对象包装在 IDictionary
在复制方面,您有很多选择。就个人而言,我认为 ToDictionary() 本身就很好。但是如果你真的不喜欢冗长,你可以将它包装在一个扩展方法中:
public static Dictionary<TKey, TValue> ToDictionary<TKey, TValue>(
this IReadOnlyDictionary<TKey, TValue> dictionary)
return dictionary.ToDictionary(x => x.Key, y => y.Value);
【讨论】:
这不是问题。这是不可能的,因为TValue
在IReadOnlyDictionary<TKey, TValue>
中是不变的。以上是关于无法将 Dictionary<string, List<string>> 转换为 IReadOnlyDictionary<string, IReadOnlyCollect的主要内容,如果未能解决你的问题,请参考以下文章
尝试保存数组,出现错误 - 无法将类型“[Data]”的值转换为预期的参数类型“[Dictionary<String, AnyObject>]”
无法将“Swift.Array<Any>”类型的值转换为“Swift.Dictionary<Swift.String, Any>”
WPF MVVM 将 Dictionary<String, List<String>> 绑定到数据网格
将 [Dictionary<String,Any?>] 转换为 [Dictionary<String,Any!>] ?迅速 3
如何将 List<Dictionary<string, byte[]> 对象添加到 Dictionary<string, byte[]> [重复]
无法使用类型为“(字符串,选项:nil,指标:nil,视图:Dictionary<String,UIView!>)”的参数列表调用“constraintsWithVisualFormat”