Reputation: 17
I noticed that key-value pairs can only be added to Dictionaries if the variable is declared as an IDictionary<TKey, TValue>
. Which caused me to dig further down the rabbit hole, leading me to discover that there seems to be an odd discrepancy:
Microsoft Docs explicitly confirm that IDictionary<TKey, TValue>
implements IEnumerable<T>
Microsoft Docs Screenshot - IDictionary Implements implements IEnumerable<T>
Using the Visual Studio's Reflector Tool on mscorlib, IDictionary<TKey, TValue>
seems to not implement IEnumerable<T>
Reflector Tool Screenshot - mscorlib, IDictionary seems to not implement IEnumerable<T>
Any explanation will be helpful to sate this curious mind!
Upvotes: 1
Views: 142
Reputation: 13763
It does show that it implements IEnumerable<T>
:
For a Dictionary<TKey, TValue>
, the collection element's type is KeyValuePair<TKey, TValue>
. In essence, a dictionary is an enumerable list of key/value pairs (of the chosen key/value types), so it implements the IEnumerable<KeyValuePair<TKey, TValue>>
interface.
The MSDN docs show both the generic IEnumerable<T>
interface, and the more concrete IEnumerable<KeyValuePair<TKey, TValue>>
, but they are referring to the same implementation. The T
in IEnumerable<T>
is effectively KeyValuePair<TKey, TValue>
.
This isn't a case of the real code missing a documented feature. It's a case of MSDN documenting the same interface implementation twice, by referring to both the generic IEnumerable<T>
and the more concrete type where it shows what T
is being defined as (i.e. KeyValuePair<TKey, TValue>
).
If you think about it, it doesn't make sense to have Dictionary<TKey, TValue> : IEnumerable<T>
since T
was never defined to begin with. Any generic type that appears after the :
must either be hardcoded or defined as a generic type before the :
, and T
is neither hardcoded nor defined, so it's not valid syntax.
You can easily confirm this behavior:
public class Foo : IEnumerable<string> { } // allowed, T is hardcoded as string
public class Foo<T> : IEnumerable<T> { } // allowed, T is defined in Foo<T>
public class Foo : IEnumerable<T> { } // error, T is neither hardcoded nor defined
Knowing this, let's look back at the dictionary:
public class Dictionary<TKey, TValue> : IEnumerable<T> // error, T is neither hardcoded nor defined
But this is valid:
public class Dictionary<TKey, TValue> : IEnumerable<KeyValuePair<TKey, TValue>>
KeyValuePair<TKey, TValue>
consists of 3 distinct types, and all of them conform to the rules:
KeyValuePair
is hardcoded (it's a known type)TKey
is a defined generic type from Dictionary<TKey, TValue>
TValue
is a defined generic type from Dictionary<TKey, TValue>
And therefore this class definition is syntactically valid.
Upvotes: 5