为什么通用类型定义实现的接口会丢失类型信息?
例如,如果您运行以下代码…
Type IListType = new List().GetType() .GetInterface("IList`1") .GetGenericTypeDefinition();
…并且您观察IListType
变量,您会发现整个Type
实例具有FullName
等所有可用属性。
但是当你运行代码时会发生什么?
Type IListType2 = typeof(List).GetInterface("IList`1")
现在,来自generics类型定义的IListType
与第一个代码示例不同:大多数Type
属性将返回null。
这个问题的主要问题是IListType == IListType2
不等于它们是相同的类型。
这是怎么回事?
这太丑了……
现在看看如果调用IListType2.GetGenericTypeDefinition()
会发生什么……它恢复了类型信息!
.NET Framework开发团队成员可以解释为什么一个奇怪地丢失其元数据的已经generics的类型定义为什么IsGenericTypeDefinition
属性设置为false
而它仍然是generics类型定义,最后,如果你调用GetGenericTypeDefinition()
在它上面,你恢复了类型信息。
这很奇怪…
以下等式将true
:
Type IListType = new List().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! Type IListType2 = typeof(List).GetInterface("IList`1").GetGenericTypeDefinition(); bool y = IListType == IListType2;
以下类型都是不同的,并且没有通过inheritance关系连接:
-
IList
-
IList
-
IList
所有这些都有不同的Type
对象,因为你可以用它们做不同的事情。 后两者是前者的专业。 第一个是generics类型定义(可以通过GetGenericTypeDefinition
获取)。
解释还有另一部分。 当你说class List
, IList
部分不等于typeof(IList<>)
因为它已经专门用于T
这不再是generics类型定义。 它是一种具体的类型,如IList
。 它专门用于将其唯一的类型参数绑定到List
专用的List
LINQPad实验:
Type bound = new List().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
的第一个版本是IList
的实际类型版本,比如说IList
。
第二个是IList
的通用定义,没有IList
的类型。
这使得两个接口不同。 有不一样的,因为第一个是第二个的具体版本。