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

Adi*_*pta 1 .net c# ienumerable idictionary visual-studio

我注意到,如果变量被声明为IDictionary<TKey, TValue>. 这让我在兔子洞里进一步挖掘,让我发现似乎有一个奇怪的差异:

  1. Microsoft Docs 明确确认IDictionary<TKey, TValue>实施IEnumerable<T>
    Microsoft Docs Screenshot - IDictionary Implements implementsIEnumerable<T>

  2. 在 mscorlib 上使用 Visual Studio 的反射器工具,IDictionary<TKey, TValue>似乎没有实现IEnumerable<T>

    反射器工具截图 - mscorlib、IDictionary 似乎没有实现 IEnumerable<T>

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

Fla*_*ter 5

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

在此处输入图片说明

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

MSDN文档表明两者的通用IEnumerable<T>接口,并且更具体的IEnumerable<KeyValuePair<TKey, TValue>>,但它们指的是相同的实现。该TIEnumerable<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
Run Code Online (Sandbox Code Playgroud)

知道了这一点,我们再回顾一下字典:

public class Dictionary<TKey, TValue> : IEnumerable<T>  // error, T is neither hardcoded nor defined
Run Code Online (Sandbox Code Playgroud)

但这有效的:

public class Dictionary<TKey, TValue> : IEnumerable<KeyValuePair<TKey, TValue>>
Run Code Online (Sandbox Code Playgroud)

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

  • KeyValuePair 是硬编码的(这是一种已知类型)
  • TKey 是一个定义的泛型类型 Dictionary<TKey, TValue>
  • TValue 是一个定义的泛型类型 Dictionary<TKey, TValue>

因此这个类定义在语法上是有效的。