Nested Interfaces: Cast IDictionary<TKey, IList<TValue>> to IDictionary<TKey, IEnumerable<TValue>>?

c#, casting, generics, interface

Solution

I would think it's fairly straightforward to cast an `IDictionary<TKey, IList<TValue>>` object to an `IDictionary<TKey, IEnumerable<TValue>>`

Absolutely not. It wouldn't be type-safe. Here's an example of why not:

// This is fine...
IDictionary<string, IList<int>> dictionary = new Dictionary<string, IList<int>>();

// Suppose this were valid...
IDictionary<string, IEnumerable<int>> badDictionary = dictionary;

// LinkedList<T> doesn't implement IList<T>
badDictionary["foo"] = new LinkedList<int>();

// What should happen now?
IList<int> bang = dictionary["foo"];

As you can see, that's going to cause problems - we'd be trying to get a `LinkedList<int>` out when we expect all the values to implement `IList<int>`. The point of generics is to be type-safe - so which line would you expect to fail? The first, third and fourth lines look pretty clearly valid to me - so the second one is the only one which can fail to compile, and it does...

Now in some cases, it can be done safely. For example, you can convert (in C# 4) from `IEnumerable<string>` to `IEnumerable<object>` because `IEnumerable<T>` only uses `T` in "output" positions.

See MSDN for more details.

EDIT: Just to clarify - it's easy to create a new dictionary with a copy of the existing key/value pairs, e.g. using link:

var copy = original.ToDictionary<TKey, IEnumerable<TValue>>(pair => pair.Key,
                                                            pair => pair.Value);

You just need to be aware that you now have two separate dictionaries.

Problem

I would think it's fairly straightforward to cast an `IDictionary<TKey, IList<TValue>>` object to an `IDictionary<TKey, IEnumerable<TValue>>`, but ``` var val = (IDictionary<TKey, IEnumerable<TValue>>)Value; ``` throws a `System.InvalidCastException`, and ``` var val = Value as IDictionary<TKey, IEnumerable<TValue>>; ``` makes `val` null. What is the proper way to cast this?

Original source