转换包含通用字典的通用字典

nic*_*s13 8 c# generics dictionary casting nested

我有:

var someConcreteInstance = new Dictionary<string, Dictionary<string, bool>>();
Run Code Online (Sandbox Code Playgroud)

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

someInterfaceInstance = (IDictionary<string, IDictionary<string, bool>>)someConcreteInstance;
Run Code Online (Sandbox Code Playgroud)

'someInterfaceInstance'是一个公共属性:

IDictionary<string, IDictionary<string, bool>> someInterfaceInstance { get; set; }
Run Code Online (Sandbox Code Playgroud)

这正确编译,但抛出运行时转换错误.

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]]'.
Run Code Online (Sandbox Code Playgroud)

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

Eri*_*ert 12

其他答案是正确的,但为了清楚地知道这是非法的,请考虑以下事项:

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?
Run Code Online (Sandbox Code Playgroud)

没有致命的手可以阻止你把老虎放入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?
Run Code Online (Sandbox Code Playgroud)

现在你把老虎放在长颈鹿类型的变量中.

如果编译器可以证明不会出现这样的情况,则通用接口协方差在C#4中是合法的.

  • @ nicodemus13:你的代码中有一个强制转换操作符; 我没有.转换运算符意味着"进行这种转换,这在编译时是非法的,并使其合法;如果在运行时证明是非法的,则抛出异常".嘿,猜猜怎么着?这就是发生的事情.你告诉编译器"假设这种非法转换会很好"然后它没有,你得到一个例外.**引用类型转换操作符的目的是将类型检查的负担从编译器转移到运行时.**负担不会消失,只是移动. (2认同)

Ali*_*tad 4

IDictionary不支持协方差。

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