6

我遇到了泛型的奇怪行为。下面是我用于测试的代码。

public static class Program
{
    public static void Main()
    {
        Type listClassType = typeof(List<int>).GetGenericTypeDefinition();
        Type listInterfaceType = listClassType.GetInterfaces()[0];

        Console.WriteLine(listClassType.GetGenericArguments()[0].DeclaringType);
        Console.WriteLine(listInterfaceType.GetGenericArguments()[0].DeclaringType);
    }
}

输出:

System.Collections.Generic.List`1[T]
System.Collections.Generic.List`1[T]

我发现第二个 Console.WriteLine 调用显示一个类而不是接口很奇怪,因为我使用了泛型类型定义。这是正确的行为吗?

我正在尝试在我的编译器中实现泛型类型推断。假设我有下面的代码。

public static class GenericClass
{
    public static void GenericMethod<TMethodParam>(IList<TMethodParam> list) { }
}

我想按如下方式调用此方法:

GenericClass.GenericMethod(new List<int>());

为了检查推理的可能性,我必须比较方法签名中的类型和传递的参数类型。但是下面的代码返回 false。

typeof(GenericClass).GetMethods()[0].GetParameters()[0].ParameterType == listInterfaceType;

我是否应该始终使用 Type.GetGenericTypeDefinition 进行此类比较?

4

2 回答 2

15

您混淆了两种都命名为 T 的不同类型。这样想:

interface IFoo<TIFOO> { }
class Foo<TFOO> : IFoo<TFOO> {}

好的,什么是泛型类型定义Foo<int>?那就是Foo<TFOO>

实现的接口是Foo<TFOO>什么?那就是IFoo<TFOO>

类型参数Foo<TFOO>什么?显然TFOO

声明 什么类型TFOOFoo<TFOO>宣布它。

类型参数IFoo<TFOO>什么?显然TFOO不是 TIFOO

声明 什么类型TFOOFoo<TFOO>宣布它。 不是 IFoo<TFOO>TFOO来自Foo.

说得通?

于 2013-03-26T16:50:50.130 回答
2

添加第二个答案,因为您添加了第二个问题:

我正在尝试在我的编译器中实现泛型类型推断......

因此,我假设您正在使用反射来构建编译器。这可能不是一个好主意。反射现在比早期的性能要好得多,但与直接使用令牌相比,它仍然是重量级的。并且反射发射不能发射所有可能的拓扑类型;在某些涉及嵌套结构类型的场景中,它会变得混乱。

我会考虑改用 CCI。我们为 Roslyn 使用了 CCI 的修改版本。

下面的代码返回 false。

typeof(GenericClass).GetMethods()[0].GetParameters()[0].ParameterType == listInterfaceType

这是正确的。参数类型 isIList<TMethodParam>listInterfaceTypeisIList<T>其中T是 声明的泛型参数类型List<T>,而不是 声明的泛型参数类型IList<T>。这些都是不同的类型。

我是否应该始终使用 Type.GetGenericTypeDefinition 进行此类比较?

如果您想查看两个泛型类型是否都是相同泛型类型的构造,是的。如果这不是您要检查的内容,那么不。

这种类型的系统很复杂,所以要非常小心。

这是使用基于令牌的方法而不是基于反射类型对象的方法的另一个原因。当您手头有标记时,区分 aTypeDef和 a会容易得多TypeRef

于 2013-03-26T18:22:41.147 回答