c# - 当值类型可以相互转换时,为什么我不能将一种值类型的字典转换为另一种值类型的字典?

标签 c# generics dictionary casting covariance

<分区>

Possible Duplicate:
In C#, why can't a List<string> object be stored in a List<object> variable

为什么以下不起作用?

List<string> castMe = new List<string>();
IEnumerable<string> getFromCast  = (IEnumerable<string>)castMe; // allowed.

Dictionary<int, List<string>> castMeDict = new Dictionary<int, List<string>>();
Dictionary<int, IEnumerable<string>> getFromDict = (Dictionary<int, IEnumerable<string>>)castMeDict;  // Not allowed

这是 Dictionary 转换机制的缺陷,还是我认为应该允许这样做?

谢谢。

最佳答案

Is this a flaw in the Dictionary casting mechanism, or in my thinking that this should be allowed?

在你的思想中。您期望字典在它们的转换中应该是协变的。他们不是,原因如下。假设它们是,并推断出可能出现的问题:

Dictionary<int, List<string>> castMeDict = 
    new Dictionary<int, List<string>>();

Dictionary<int, IEnumerable<string>> getFromDict = 
    (Dictionary<int, IEnumerable<string>>)castMeDict;

castMeDict[123] = new List<string>();
IEnumerable<string> strings = getFromDict[123]; // No problem!
getFromDict[123] = new string[] { "hello" }; // Big problem!

字符串数组可转换为 IEnumerable<string>但不是 List<string> .您只需将不是字符串列表的内容放入只能获取字符串列表的字典中。

在 C# 中,如果满足以下所有条件,泛型类型可能是协变或逆变的:

  • 您使用的是 C# 4 或更高版本。
  • 变化的通用类型是接口(interface)或委托(delegate)。
  • 变体可证明是类型安全的。 (C# 规范描述了我们用来确定方差安全性的规则。可以下载 C# 4.0 版本文档文件 [here]。请参阅第 23.5 节。)
  • 不同的类型参数都是引用类型。
  • 该类型已被特别标记为安全的变化。

字典不满足这些条件中的大部分——它不是接口(interface)或委托(delegate),它不能证明是安全的,并且该类型没有被标记为安全的变化。因此,字典没有差异。

IEnumerable<T>相比之下,确实满足所有这些条件。您可以转换 IEnumerable<string>IEnumerable<object>在 C# 4 中。

如果您对方差主题感兴趣,请考虑阅读我关于该主题的两打文章:

http://blogs.msdn.com/b/ericlippert/archive/tags/covariance+and+contravariance/

关于c# - 当值类型可以相互转换时,为什么我不能将一种值类型的字典转换为另一种值类型的字典?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8567206/

相关文章:

c# - for 和 foreach 在闭包方面有什么区别

c# - 单击时功能区按钮不触发 onAction 设置的事件

c# - 从方法签名中删除通用参数

python - 将子字符串转换为字典

json - 违反mapKeysMonotonic前提条件

c# - 转换为不排除表单成员的接口(interface)

c# - HighChart xAxis 日期时间值

c# - 使用基类列表中的项目到泛型方法

c# - 我怎样才能使这段代码更通用

python - 如何在 python 中使用 OrderedDict 将值列表分配给键