C# 为什么开放泛型类型的基类型不开放?
考虑下面的一段代码:C# 为什么开放泛型类型的基类型不开放?,c#,reflection,C#,Reflection,考虑下面的一段代码: public class A<T> { } public class B<T> : A<T> { } 其中b的值为1。因此,它是使用一个不存在的名称“T”类型关闭的,只有对它执行GetGenericTypeDefinition操作,它才能再次打开。这是为什么?该属性返回用作封闭泛型类型的泛型参数的类型,对于开放泛型类型,它返回emtpy数组 之所以typeof(B).BaseType.GenericTypeArguments不返回空数
public class A<T> { }
public class B<T> : A<T> { }
其中b
的值为1
。因此,它是使用一个不存在的名称“T”类型关闭的,只有对它执行GetGenericTypeDefinition
操作,它才能再次打开。这是为什么?该属性返回用作封闭泛型类型的泛型参数的类型,对于开放泛型类型,它返回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);
这表明B
类型的BaseType
确实是一个封闭类型,其泛型参数为类a
的“虚拟”泛型类型
因此,它是使用一个不存在的名为“T”的类型关闭的,只有对它执行GetGenericTypeArgument操作,它才能再次打开。为什么呢
因为提供了一个类型参数--B
的类型参数
看看您是如何指定基类的:
public class B<T> : A<T>
这里,B
的基类是A
,您可以通过询问类型参数来确定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
}
}
使用系统;
运用系统反思;
使用System.Collections.Generic;
公共A类{}
公共B类:A{}
班级计划
{
静态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
//显示B中的T与列表中的T不同
Console.WriteLine(bBaseArguments[0]==listT);//False
Console.WriteLine(bBaseArguments[1]==typeof(int));//True
}
}
System.Type类没有名为GetGenericTypeArguments
的方法。你的意思是getgenericalarguments
?@Wazner:是的,修正了。-我得到0和1。此外,Console.WriteLine(typeof(B).BaseType.GenericTypeArguments[0]。FullName==null)代码>为true。是的,我很抱歉,但我在我的示例中首先使用了错误的方法。请尝试当前的一个。还要注意,在使用泛型时,MetadataToken
不是很好的标识符,因为所有A
、A
和例如A
都将具有相同的值。具体的泛型实现是在运行时从相同的IL实体(因此具有相同的令牌)生成的。我唯一可以补充的是,您可以再次将其作为泛型类型定义(这也隐式地演示了它是如何工作的,因为它是:-)。例如:typeof(B).BaseType.GetGenericTypeDefinition().GenericTypeArguments.Length
将再次为您提供0。
704643073
704643074
704643074
public class B<T> : A<T>
public class A<T1, T2> { }
public class B<T> : A<T, int> { }
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
}
}