为什么通用类型定义实现的接口会丢失类型信息?
Why a generic type definition implemented interfaces lose type information?
例如,如果您 运行 以下代码...
Type IListType = new List<string>().GetType()
.GetInterface("IList`1")
.GetGenericTypeDefinition();
...观察 IListType
变量,您会发现整个 Type
实例具有所有可用的属性,如 FullName
和其他。
但是当你运行下面的代码时会发生什么?
Type IListType2 = typeof(List<>).GetInterface("IList`1")
现在 IListType
从通用类型定义中得到的与第一个代码示例不同:大多数 Type
属性将 return 为 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<T>
的实际键入版本,比方说 IList<string>
。
第二个是 IList<T>
的通用定义,没有 T
的类型。
这使得两个界面不同。不一样,因为第一个是第二个的具体版本。
以下类型都是不同的,没有继承关系:
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
例如,如果您 运行 以下代码...
Type IListType = new List<string>().GetType()
.GetInterface("IList`1")
.GetGenericTypeDefinition();
...观察 IListType
变量,您会发现整个 Type
实例具有所有可用的属性,如 FullName
和其他。
但是当你运行下面的代码时会发生什么?
Type IListType2 = typeof(List<>).GetInterface("IList`1")
现在 IListType
从通用类型定义中得到的与第一个代码示例不同:大多数 Type
属性将 return 为 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<T>
的实际键入版本,比方说 IList<string>
。
第二个是 IList<T>
的通用定义,没有 T
的类型。
这使得两个界面不同。不一样,因为第一个是第二个的具体版本。
以下类型都是不同的,没有继承关系:
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