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

时间:2015-11-18 09:40:26

标签: c# .net generics reflection equality

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

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属性设置为{{1}虽然它仍然是泛型类型定义,但最后,如果你在其上调用false,则可以恢复类型信息。

这很奇怪......

以下等式为GetGenericTypeDefinition()

true

2 个答案:

答案 0 :(得分:7)

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

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

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

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

答案 1 :(得分:2)

IList<T>的第一个版本是IList<T>的实际类型版本,让我们说IList<string>

第二个是IList<T>的通用定义,没有T的类型。

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