为什么打开泛型类型的基本类型未打开?

时间:2015-08-19 09:11:14

标签: c# reflection

考虑下面的一段代码:

public class A<T> { }

public class B<T> : A<T> { }

在这种情况下:

var a = typeof(A<>).GenericTypeArguments.Length;

a的值为0,这并不奇怪。然而,这对我来说是出乎意料的:

var b = typeof(B<>).BaseType.GenericTypeArguments.Length;

其中b的值为1。因此,它使用不存在的名称“T”关闭,只在其上执行GetGenericTypeDefinition使其再次打开。那是为什么?

2 个答案:

答案 0 :(得分:17)

  

因此,它使用不存在的名称“T”关闭,并且仅对其执行GetGenericTypeArgument使其再次打开。那是为什么?

因为 提供了一个类型参数 - B的类型参数。

看看你是如何指定基类的:

public class B<T> : A<T>

如果T中的A<T>不是类型参数,那么它是什么?仅仅因为类型参数本身是一个类型参数并不意味着它没有被指定为类型参数。

考虑一下:

public class A<T1, T2> { }

public class B<T> : A<T, int> { }

此处,B<T>的基类是A<T, int> - 您可以通过询问类型参数来确定已指定int。您还可以显示T的来源:

using System;
using System.Reflection;
using System.Collections.Generic;

public class A<T1, T2> { }

public class B<T> : A<T, int> { }

class Program
{
    static void Main()
    {
        var bT = typeof(B<>).GetTypeInfo().GenericTypeParameters[0];
        var listT = typeof(List<>).GetTypeInfo().GenericTypeParameters[0];
        var bBaseArguments = typeof(B<>).BaseType.GenericTypeArguments;
        Console.WriteLine(bBaseArguments[0] == bT); // True
        // Shows that the T from B<T> isn't the same as the T from List<T>
        Console.WriteLine(bBaseArguments[0] == listT); // False
        Console.WriteLine(bBaseArguments[1] == typeof(int)); // True
    }
}

答案 1 :(得分:0)

Type.GenericTypeArguments属性返回用作封闭泛型类型的通用参数的类型,对于开放泛型类型,它返回一个emtpy数组。

typeof(B<>).BaseType.GenericTypeArguments不返回空数组的原因是因为它不是开放的泛型类型。

为了说明这种行为,我使用Type.MetadataToken来识别类型。

Console.WriteLine(typeof(A<>).GetGenericArguments()[0].MetadataToken);
Console.WriteLine(typeof(B<>).GetGenericArguments()[0].MetadataToken);
Console.WriteLine(typeof(B<>).BaseType.GetGenericArguments()[0].MetadataToken);

这会在屏幕上打印以下内容(数字会有所不同,但相等会保持不变):

704643073
704643074
704643074

这表明类型BaseType的{​​{1}}确实是一个封闭类型,其通用参数是类B<>的'虚拟'泛型类型。