Consider a piece of the code below:
public class A<T> { }
public class B<T> : A<T> { }
In such case:
var a = typeof(A<>).GenericTypeArguments.Length;
a
has the value 0
, which is not surprising. This, however, is somehow unexpected for me:
var b = typeof(B<>).BaseType.GenericTypeArguments.Length;
where b
has the value 1
. So it is closed using a non-existing type of name "T" and only doing GetGenericTypeDefinition
on it makes it open again. Why is that?
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?
Because there is one type argument provided - the type parameter to B
.
Look at how you're specifying the base class:
public class B<T> : A<T>
What's the T
in A<T>
if it's not a type argument? Just because the type argument is itself a type parameter doesn't mean it's not being specified as a type argument.
Consider this:
public class A<T1, T2> { }
public class B<T> : A<T, int> { }
Here, the base class of B<T>
is A<T, int>
- and you can determine that the int
has been specified by asking for the type arguments. You can also show where the T
comes from:
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
}
}
See more on this question at Stackoverflow