Aditya Gupta
Aditya Gupta

Reputation: 17

Why does the reflector not show that IDictionary<TKey, TValue> implements IEnumerable<T>?

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:

  1. Microsoft Docs explicitly confirm that IDictionary<TKey, TValue> implements IEnumerable<T>
    Microsoft Docs Screenshot - IDictionary Implements implements IEnumerable<T>

  2. 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

Answers (1)

Flater
Flater

Reputation: 13763

It does show that it implements IEnumerable<T>:

enter image description here

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

Related Questions