Casting a shared dictionary containing a shared dictionary

I have:

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

and I want to pass it to the interface version, that is:

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

'someInterfaceInstance' is publicly available:

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

It compiles correctly, but throws an execution cast error.

 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]]'. 

What am I missing? (Problems with a nested generic type / Property?)

+8
dictionary generics casting c # nested
source share
3 answers

IDictionary does not support covariance.

Look here IDictionary <TKey, TValue> in .NET 4 is not covariant

+4
source share

Other answers are correct, but in order to be very clear why this is illegal, consider the following:

 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? 

No deadly hand can stop you from putting a tiger in the IAnimals dictionary. But this dictionary is actually limited to contain only giraffes.

For the same reason, you cannot go the other way:

 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? 

Now you put the tiger in a giraffe type variable.

The general covariance of an interface is only legal in C # 4, if the compiler can prove that such situations cannot occur.

+11
source share

The most you can do is

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

The reason your internal dictionary cannot be specified here in different ways (or via translation) is because although Dictionary<string, bool> is IDictionary<string, bool> , not all IDictionary objects will be Dictionary objects . Thus, getting a clean interface stroke will then apparently allow you to add other pairs of <string, IDictionary<string, bool>> to the original collection, when, obviously, there may be type violations for the original object. Therefore, this is not supported.

+1
source share

All Articles