【问题标题】:Casting a generic dictionary containing a generic dictionary转换包含通用字典的通用字典
【发布时间】:2011-08-03 22:23:11
【问题描述】:

我有:

var someConcreteInstance = new Dictionary<string, Dictionary<string, bool>>();

我希望将其转换为接口版本,即:

someInterfaceInstance = (IDictionary<string, IDictionary<string, bool>>)someConcreteInstance;

'someInterfaceInstance' 是一个公共属性:

IDictionary<string, IDictionary<string, bool>> someInterfaceInstance { get; set; }

这可以正确编译,但会引发运行时转换错误。

Unable to cast object of type 'System.Collections.Generic.Dictionary`2[System.String,System.Collections.Generic.Dictionary`2[System.String,System.Boolean]]' to type 'System.Collections.Generic.IDictionary`2[System.String,System.Collections.Generic.IDictionary`2[System.String,System.Boolean]]'.

我错过了什么? (嵌套泛型类型/属性的问题?)

【问题讨论】:

  • 你不能把原来的内部字典类型改成IDictionary&lt;&gt; 吗?这将简化事情,通常这不需要对填充字典的代码进行大的更改。
  • @digEmAll:根据埃里克的回答,这只是解决了问题,并没有解决问题。
  • 不,我在问你为什么不这样做:var someConcreteInstance = new Dictionary&lt;string, IDictionary&lt;string, bool&gt;&gt;(); 而不是你原来的行?这可以解决问题(你甚至不需要演员表),但当然你可能有一些理由离开你的原始代码......

标签: c# generics dictionary casting nested


【解决方案1】:

其他答案是正确的,但要清楚为什么这是非法的,请考虑以下几点:

interface IAnimal {}
class Tiger : IAnimal {}
class Giraffe : IAnimal {}
...
Dictionary<string, Giraffe> d1 = whatever;
IDictionary<string, IAnimal> d2 = d1; // suppose this were legal
d2["blake"] = new Tiger(); // What stops this?

没有凡人的手可以阻止您将老虎放入 IAnimals 字典中。但该字典实际上仅限于包含长颈鹿。

出于同样的原因,你也不能走另一条路:

Dictionary<string, IAnimal> d3 = whatever;
d3["blake"] = new Tiger(); 
IDictionary<string, Giraffe> d4 = d3; // suppose this were legal
Giraffe g = d4["blake"]; // What stops this?

现在您将老虎放入长颈鹿类型的变量中。

如果编译器能够证明这种情况不会出现,泛型接口协变在 C# 4 中才合法。

【讨论】:

  • 你确定最后一行写的很清楚吗?我的原始代码编译良好,但会引发运行时错误,因此编译器似乎允许这种情况。
  • @nicodemus13:您的代码中有一个强制转换运算符;我的没有。强制转换运算符的意思是“将这个在编译时非法的转换变为合法;如果在运行时证明是非法的,则抛出异常”。嘿,你猜怎么着?这就是正在发生的事情。你告诉编译器“假设这种非法转换会正常工作”,然后它不会,你会得到一个异常。 引用类型转换运算符的目的是将类型检查的负担从编译器转移到运行时。负担并没有消失,它只是移动了。
  • “长颈鹿,长颈鹿,燃烧的明亮/在夜晚的森林中”。好在 C# 类型系统避免了这样的悲剧!
【解决方案2】:

IDictionary 不支持协方差。

看这里 IDictionary<TKey, TValue> in .NET 4 not covariant

【讨论】:

  • 哦,这就是问题所在! (即使在 .net 4 中?)您对如何获得我想要的结果有任何建议吗?
  • 取决于你想要做什么。发布另一个关于您要达到的目标的问题,并要求最好的设计。
【解决方案3】:

你能做的最多是

IDictionary<string, Dictionary<string, bool>> viaInterface = someConcreteInstance

您的内部字典在此处不能以不同方式引用(或通过强制转换)的原因是,虽然 Dictionary&lt;string, bool&gt;IDictionary&lt;string, bool&gt;,但并非所有 IDictionary 对象都是 Dictionary 对象。因此,当原始对象显然可能存在类型冲突时,获得纯接口转换似乎允许您将其他 &lt;string, IDictionary&lt;string, bool&gt;&gt; 对添加到原始集合中。因此,这不受支持。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-04-22
    • 1970-01-01
    • 1970-01-01
    • 2021-07-23
    • 2019-04-21
    • 1970-01-01
    • 2018-08-04
    相关资源
    最近更新 更多