'Why does upcasting IDictionary<TKey, TValue> to IEnumerable<object> fail?

See the following code snippet:

(IEnumerable<object>)new Dictionary<string, string>()

The above cast will throw an invalid cast exception.

Actually, IDictionary<TKey, TValue> also indirectly implements IEnumerable<out T>, because it also implements ICollection<T>. That is, the whole cast should be valid.

In fact, for me it is even more strange that if I run the whole cast on a debugger watch slot, it works!

Enter image description here

What's going on?



Solution 1:[1]

That dictionary does implement IEnumerable<KeyValuePair<TKey, TValue>> and IEnumerable, but IEnumerable of a struct is not the same as IEnumerable of an object. Variance only works for reference-types. KeyValuePair<K, V> is a struct and not a class.

This does work at my end and should be the logical choice:

var x = (IEnumerable)new Dictionary<string, string>();

As a sample, this does work:

List<string> l = new List<string>();
var x = (IEnumerable<object>)l;

But this one doesn't:

List<DateTime> l2 = new List<DateTime>();
var x = (IEnumerable<object>)l2;

Clearly indicating the struct is the problem.

(Why it works in your Watch windows, I don't know)

Solution 2:[2]

I think this is because KeyValuePair is a Value-Type.

This would fail:

List<int> ints = new List<int>();
var objs = (IEnumerable<object>)ints;

This would work:

List<string> ints = new List<string>();
var objs = (IEnumerable<object>)ints;

same goes for the dictionary.

Solution 3:[3]

If you really can't live with plain IEnumerable, try this:

new Dictionary<string, string>().Cast<object>();

Solution 4:[4]

This is strange. Your code snippet works fine with .NET 4.0. I suggest you cast to IEnumerable.

Read: IDictionary Interface (MSDN)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 StayOnTarget
Solution 2 Zein Makki
Solution 3 Paulo Morgado
Solution 4 Peter Mortensen