为什么反射器不显示 IDictionary<TKey, TValue> 实现 IEnumerable<T>?

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

我注意到,如果变量声明为 IDictionary<TKey, TValue>,则键值对只能添加到字典中。这让我进一步挖掘兔子洞,让我发现似乎有一个奇怪的差异:

  1. Microsoft 文档明确确认 IDictionary<TKey, TValue> 实现了 IEnumerable<T>
    Microsoft Docs Screenshot - IDictionary Implements implements IEnumerable<T>

  2. 在 mscorlib 上使用 Visual Studio 的 Reflector Tool,IDictionary<TKey, TValue> 似乎没有实现 IEnumerable<T>

    Reflector Tool Screenshot - mscorlib, IDictionary seems to not implement IEnumerable<T>

任何解释都将有助于满足这个好奇心!

确实表明它实现了IEnumerable<T>:

对于 Dictionary<TKey, TValue>,集合元素的类型是 KeyValuePair<TKey, TValue>。本质上,字典是 key/value 对(所选 key/value 类型)的可枚举列表,因此它实现了 IEnumerable<KeyValuePair<TKey, TValue>> 接口。

MSDN 文档显示 通用 IEnumerable<T> 接口和更具体的 IEnumerable<KeyValuePair<TKey, TValue>>,但它们指的是相同的实现。 IEnumerable<T> 中的 T 实际上是 KeyValuePair<TKey, TValue>.

这不是真实代码缺少记录功能的情况。这是 MSDN 两次记录相同接口实现的情况,通过引用通用 IEnumerable<T> 更具体的类型,它显示了 T 被定义的内容作为(即 KeyValuePair<TKey, TValue>)。


如果您考虑一下,Dictionary<TKey, TValue> : IEnumerable<T> 是没有意义的,因为 T 从来没有定义过。出现在 : 之后的任何泛型类型必须被硬编码或定义为 : 之前的泛型类型,而 T 既没有硬编码也没有定义,因此它不是有效语法。

您可以轻松确认此行为:

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

知道了这些,我们再回头看看字典:

public class Dictionary<TKey, TValue> : IEnumerable<T>  // error, T is neither hardcoded nor defined

但是这个有效的:

public class Dictionary<TKey, TValue> : IEnumerable<KeyValuePair<TKey, TValue>>

KeyValuePair<TKey, TValue>由3种不同的类型组成,它们都符合规则:

  • KeyValuePair 是硬编码的(这是已知类型)
  • TKeyDictionary<TKey, TValue>
  • 定义的泛型类型
  • TValueDictionary<TKey, TValue>
  • 定义的泛型类型

因此这个 class 定义在句法上是有效的。