为什么泛型类型定义实现的接口会丢失类型信息

本文关键字:类型 信息 接口 泛型类型定义 实现 为什么 | 更新日期: 2023-09-27 18:22:24

例如,如果您运行以下代码。。。

Type IListType = new List<string>().GetType()
                                   .GetInterface("IList`1")
                                   .GetGenericTypeDefinition();

当您观察IListType变量时,您会发现整个Type实例具有所有可用属性,如FullName和其他属性。

但是当你运行下面的代码时会发生什么呢?

Type IListType2 = typeof(List<>).GetInterface("IList`1")

现在,从泛型类型定义中获得的IListType与第一个代码示例不同:大多数Type属性将返回null。

这方面的主要问题是,当它们是同一类型时,IListType == IListType2并不相等。

怎么回事?

这太难看了

现在看看如果您调用IListType2.GetGenericTypeDefinition()会发生什么。。。它恢复类型信息!

如果.NET Framework开发团队成员能够向我们解释为什么已经是泛型的类型定义(它奇怪地丢失了元数据)的IsGenericTypeDefinition属性设置为false,而它仍然是泛型类型定义,那么这将是一件很好的事,最后,如果您对它调用GetGenericTypeDefinition(),则可以恢复类型信息。

这很奇怪

以下等式为true:

Type IListType = new List<string>().GetType()
                        .GetInterface("IList`1")
                        .GetGenericTypeDefinition();
// Got interface is "like a generic type definition" since it has
// no type for T generic parameter, and once you call 
// GetGenericTypeDefinition() again, it recovers the lost metadata 
// and the resulting generic type definition equals the one got from
// List<string>!
Type IListType2 = typeof(List<>).GetInterface("IList`1").GetGenericTypeDefinition();
bool y = IListType == IListType2;

为什么泛型类型定义实现的接口会丢失类型信息

以下类型都不同,并且没有通过继承关系连接:

  • IList<T>
  • IList<int>
  • IList<string>

所有这些都有不同的Type对象,因为您可以用它们做不同的事情。后两者是前者的专门化。第一个是泛型类型定义(可以通过GetGenericTypeDefinition获得)。

解释还有另一部分。当你说class List<T> : IList<T>时,IList<T>部分是而不是等于typeof(IList<>),因为它已经专用于T。这不再是泛型类型定义。它是一种具体的类型,如IList<int>。它专门将其唯一的类型参数绑定到List<T>专门用于的T


LINQPad:的实验

Type bound = new List<string>().GetType().GetInterface("IList`1");
bound.GenericTypeArguments.Single().Dump(); //string

Type bound = typeof(List<>).GetInterface("IList`1");
bound.GenericTypeArguments.Single().Dump(); //"T"
(bound.GenericTypeArguments.Single() == typeof(List<>).GetGenericArguments().Single()).Dump(); //true

IList<T>的第一个版本是IList<T>的实际类型化版本,比如说IList<string>

第二个是CCD_ 27的一般定义,没有CCD_ 28的类型。

这使得两个接口不同。没有相同的,因为第一个是第二个的具体版本。