【问题标题】:IDictionary, Dictionary字典,字典
【发布时间】:2009-06-30 15:40:57
【问题描述】:

我有:

IDictionary<string, IDictionary<string, IList<long>>> OldDic1; 

(仅出于说明目的,它被实例化并具有值 - 在其他地方)

为什么我可以这样做:?

Dictionary<string, IDictionary<string, IList<long>>> dic1 = 
  OldDic1 as Dictionary<string, IDictionary<string, IList<long>>>;

执行此行后基本上 dic1 具有来自 OldDic1 的所有值;有效。

但是当我这样做时:

Dictionary<string, Dictionary<string, List<long>>> dic1 = 
  OldDic1 as Dictionary<string, Dictionary<string, List<long>>>;

我得到 null,它与强制转换相同,只是它不会崩溃,而是返回 null。所以问题是为什么我不能将它从接口转换为类型?有没有解决方案,除了首先改变它的存储方式?

【问题讨论】:

  • 铸造有点混乱。当进行这种类型的转换(或使用“as”)时,基本上你所做的就是检查对象是否实际上是存储中的指定类型。您不是在创建具有该类型的新对象,您只是在检查。如果不清楚,请尝试阅读这篇文章:blogs.msdn.com/ericlippert/archive/2009/03/19/…

标签: c# .net dictionary idictionary


【解决方案1】:

你只能重铸最外层的接口/类名,不能重铸泛型参数。您的第二次转换不起作用的原因与您无法从一种数组类型转换为另一种数组类型的原因相同,即使您可以转换“包含”对象也是如此。原因如下:

List<object> objects;
List<string> strings;

objects = strings as List<object>;
// Uh oh, that's not a string!
objects.Add(42); 

objects = new List<object> { "The", "answer", "is", 42 };
// Uh oh, now strings contains an integer?
strings = objects as List<string>;

在你的第二种情况下也会发生同样的事情。您可以将某种IDictionary 添加到OldDic1,这实际上不是Dictionary,然后dic1 会爆炸。它将具有非Dictionary 值。呸呸呸!

因此,当您拥有容器时,您可以从 IList&lt;X&gt; 更改为 List&lt;X&gt; 并返回,只要 X 对于每个容器相同

【讨论】:

  • 如果数组元素类型是可以转换的引用类型,则可以在 C# 中将一种数组类型转换为另一种。如果元素类型是 ref 类型,则数组转换在 C# 中是协变的。这种协方差实际上不是类型安全的!不幸的是,这被添加到类型系统中。
【解决方案2】:

该行为与 C# 中的 as keyword 有关。字典与 IDictionary 不同。

如果您以另一种方式进行转换,您也许可以让它在 .NET 的下一版本中工作,该版本增加了对 covariance and contravariance 的支持。

您可能想要确定为什么需要转换为具体 Dictionary/List 的解决方案,如果需要,则更改类型的存储。

【讨论】:

  • 我必须转换为具体类型的原因是因为 DataContractJsonSerializer,它需要类型。当对象是具体类型时,我可以说 dic1.GetType(),但是如果我在接口上执行此操作,DataContractJsonSeralizer .writeobject 会抛出异常
猜你喜欢
  • 2017-02-05
  • 2021-07-24
  • 2019-10-17
  • 1970-01-01
  • 2022-11-08
  • 2018-08-21
  • 1970-01-01
  • 1970-01-01
  • 2020-12-15
相关资源
最近更新 更多