为什么开放泛型的基类型不开放?
Why is the base type of an open generic type not open?
考虑下面的一段代码:
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
使其再次打开。这是为什么?
Type.GenericTypeArguments属性returns作为泛型参数的类型,对于封闭的泛型,对于开放的泛型,return是一个空数组。
typeof(B<>).BaseType.GenericTypeArguments
不是 return 空数组的原因是因为它不是开放泛型类型。
为了说明这种行为,我使用 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
这表明 B<>
类型的 BaseType
确实是一个封闭类型,其泛型参数为 class A<>
的 'virtual' 泛型类型。
So it is closed using a non-existing type of name "T" and only doing GetGenericTypeArgument on it makes it open again. Why is that?
因为 是 提供的一种类型参数 - B
.
的类型参数
看看你是如何指定基数的 class:
public class B<T> : A<T>
如果 A<T>
中的 T
不是类型参数,那它是什么?仅仅因为类型参数本身是类型参数并不意味着它没有被指定为类型参数。
考虑一下:
public class A<T1, T2> { }
public class B<T> : A<T, int> { }
这里,B<T>
的基数 class 是 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
}
}
考虑下面的一段代码:
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
使其再次打开。这是为什么?
Type.GenericTypeArguments属性returns作为泛型参数的类型,对于封闭的泛型,对于开放的泛型,return是一个空数组。
typeof(B<>).BaseType.GenericTypeArguments
不是 return 空数组的原因是因为它不是开放泛型类型。
为了说明这种行为,我使用 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
这表明 B<>
类型的 BaseType
确实是一个封闭类型,其泛型参数为 class A<>
的 'virtual' 泛型类型。
So it is closed using a non-existing type of name "T" and only doing GetGenericTypeArgument on it makes it open again. Why is that?
因为 是 提供的一种类型参数 - B
.
看看你是如何指定基数的 class:
public class B<T> : A<T>
如果 A<T>
中的 T
不是类型参数,那它是什么?仅仅因为类型参数本身是类型参数并不意味着它没有被指定为类型参数。
考虑一下:
public class A<T1, T2> { }
public class B<T> : A<T, int> { }
这里,B<T>
的基数 class 是 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
}
}