Example:
class Base<T>{}
class Child<T> : Base<T>{}
typeof( Base<> ).IsGenericTypeDefinition; // == true ie. parameterless
typeof( Child<> ).BaseType.IsGenericTypeDefinition; // == false wtf???
// Eventually
typeof( Base<> ) != typeof( Child<> ).BaseType;
Due to this feature typeof( Child<> ).IsSubclassOf( typeof( Base<> ) )
is not working.
I have read the documentation here and it explains the differences between IsGenericType
and IsGenericTypeDefinition
.
Your BaseType
falls into this category: open constructed type
The ContainsGenericParameters property is true.
Examples are a generic type that has unassigned type parameters, a type that is nested in a generic type definition or in an open constructed type, or a generic type that has a type argument for which the ContainsGenericParameters property is true.
It is not possible to create an instance of an open constructed type.
So in order for a type definition to be generic you must be able to create an instance from it. But in this case, BaseType
is an open constructed type and it is bound to it's inheritor: Child<T>
, If you create a Child<int>
then the base becomes Base<int>
, not vice versa.
Therefore you can't create a generic type instance directly from the BaseType
by calling MakeGenericType
because it's type parameter is declared in the inheritor class Child<T>
.
I've found some information in the book Professional .NET 2.0 Generics
, section Reflection and Generic Inheritance
.
the inherited type is bound indirectly to the TValue parameter of the subclass.
I did some simple tests:
var arg = typeof( Base<> ).GetGenericArguments()[ 0 ];
Console.WriteLine( arg.DeclaringType ); // Base`1[T]
arg = typeof( Child<> ).BaseType.GetGenericArguments()[ 0 ];
Console.WriteLine( arg.DeclaringType ); // Child`1[T]
Term "parameterless" confused me.
Actually even types with no specified generic parameters have parameters. It's types with arg.IsGenericParameter == true
.
And these types can also be inherited. As in the usual case:
typeof( Child<int> ).BaseType == typeof( Base<int> );
The same way with parameterless case:
typeof( Base<> ) != typeof( Child<> ).BaseType; // it's something like: Base<T>.T != Child<T>.T
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With