In reflection the unconstructed generic type, say C<>
is conflated with the instance type C<T>
.
This is perhaps less than theoretically pure; I think of these as very different entities. I think of one as the symbol "C with one type parameter" and the other as a compile time type C<T>
. In code, C<>
and C<T>
are not synonyms for each other; you can make a field of the latter type if T is in scope, but you cannot ever make a field of the former type.
That the reflection library gives you the type of the instance type when you ask for the unconstructed type is not all bad though. What would you do with the unconstructed type? There's nothing you really can do with it. But with the instance type, you can say "substitute int for T" in here.
The real benefit of getting C<T>
when you ask for typeof(C<>)
is that this always gives you the unconstructed type. Compare:
class C<T>
{
public static Type CT() { return typeof(C<T>); }
public static Type JustC() { return typeof(C<>); }
}
When you call CT, what are you going to call it on? There's no type C<T>
to call CT on. You can call C<int>.CT
in which case you'll get back C<int>
, not C<T>
. The only way to get the type C<>
constructed with T is to ask for typeof(C<>)
.
Does that make sense?
I haven't yet covered reflection ( I have a vague idea of what it is )
Reflection is simply the library of code that allows you to get information about your code in the code itself. "typeof" gives you a Type object which you can then "reflect" upon to find out information about the type.
I'm not sure I understand what you mean by "even when T is not in scope"
The way I said it was confusing. I've rephrased it.