求助:无法将Dictionary<string, List<string>>转换为IReadOnlyDictionary<string, IReadOnlyCollection<string>>的原因解析
Dictionary<string, List<string>>转换为IReadOnlyDictionary<string, IReadOnlyCollection<string>>? 这个错误的核心原因和C#泛型的不变性有关,咱们一步步拆解清楚:
接口的泛型参数特性限制
IReadOnlyDictionary<TKey, TValue>这个接口在TValue参数上是不变的——也就是说,它不支持把IReadOnlyDictionary<TKey, TDerived>隐式转换成IReadOnlyDictionary<TKey, TBase>,哪怕TDerived是TBase的子类(比如List<string>确实是IReadOnlyCollection<string>的子类)。
对比一下IReadOnlyCollection<out T>,它的T是协变的(用out标记),所以你可以直接把List<string>赋值给IReadOnlyCollection<string>,但这个协变特性不会传递到包含它的IReadOnlyDictionary上,因为字典接口本身没给TValue加out修饰符。具体类的实现范围
你的变量x是Dictionary<string, List<string>>,它实现的是IReadOnlyDictionary<string, List<string>>,而不是IReadOnlyDictionary<string, IReadOnlyCollection<string>>。C#不会自动帮你把字典里的每个List<string>都转换成IReadOnlyCollection<string>,因为这涉及到整个泛型类型参数的替换,而不是单个元素的简单转换。
解决办法
如果你需要把x转换成目标类型,可以手动处理每个键值对,把值的类型转换过去:
IReadOnlyDictionary<string, IReadOnlyCollection<string>> y = x.ToDictionary(kv => kv.Key, kv => (IReadOnlyCollection<string>)kv.Value);
或者更简洁地利用类型推断:
var y = x.ToDictionary(k => k.Key, v => v.Value as IReadOnlyCollection<string>);
这样就能得到符合要求的IReadOnlyDictionary<string, IReadOnlyCollection<string>>实例了。
内容的提问来源于stack exchange,提问作者Yahav

