简体   繁体   中英

Casting a generic dictionary containing a generic dictionary

I have:

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

and I wish to cast it to an interface version, ie:

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

'someInterfaceInstance' is a public property:

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

This compiles correctly, but throws a runtime casting 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 the nested generic type/Property?)

The other answers are right, but just to be crystal clear as to 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 mortal hand can stop you putting a tiger into a dictionary of IAnimals. But that dictionary is actually constrained to contain only giraffes.

For the same reason you can't go the other way either:

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're putting a tiger in a variable of type giraffe.

Generic interface covariance is only legal in C# 4 if the compiler can prove that situations like this cannot arise.

IDictionary does not support covariance.

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

The most you will be able to do is

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

The reason your inner dictionary cannot be referenced differently here (or via a cast) is that while Dictionary<string, bool> is an IDictionary<string, bool> , not all IDictionary objects will be Dictionary objects. As such, obtaining a pure interface cast would then seemingly allow you to add other <string, IDictionary<string, bool>> pairs to the original collection, when clearly there could be type violations for the original object. Therefore, this is not supported.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM