For example, if you run the following code...
Type IListType = new List<string>().GetType()
.GetInterface("IList`1")
.GetGenericTypeDefinition();
...and you watch IListType
variable, you'll find that the whole Type
instance has all properties available like FullName
and others.
But what happens when you run the code bellow?
Type IListType2 = typeof(List<>).GetInterface("IList`1")
Now IListType
got from a generic type definition isn't the same as the first code sample: most Type
properties will return null.
The main issue with this is that IListType == IListType2
doesn't equal while they're the same type.
What's going on?
This is ugly...
Now see what happens if you call IListType2.GetGenericTypeDefinition()
... It recovers the type information!
It would be great that a .NET Framework development team member could explain us why an already generic type definition which has strangely lost its metadata has IsGenericTypeDefinition
property set to false
while it's still a generic type definition, and finally, if you call GetGenericTypeDefinition()
on it, you recover the type information.
This is strange...
The following equality will be true
:
Type IListType = new List<string>().GetType()
.GetInterface("IList`1")
.GetGenericTypeDefinition();
// Got interface is "like a generic type definition" since it has
// no type for T generic parameter, and once you call
// GetGenericTypeDefinition() again, it recovers the lost metadata
// and the resulting generic type definition equals the one got from
// List<string>!
Type IListType2 = typeof(List<>).GetInterface("IList`1").GetGenericTypeDefinition();
bool y = IListType == IListType2;
The following types are all different and not connected by an inheritance relationship:
IList<T>
IList<int>
IList<string>
All of these have different
Type
objects because you can do different things with them. The latter two are the specializations of the former. The first is the generic type definition (which you can obtain throughGetGenericTypeDefinition
).There is another part to the explanation. When you say
class List<T> : IList<T>
then theIList<T>
part is not equal totypeof(IList<>)
because it is already specialized toT
. This is no longer a generic type definition. It is a concrete type such asIList<int>
. It is specialized to bind its only type argument to theT
thatList<T>
was specialized to.Experiment for LINQPad:
The first version of
IList<T>
is the actual typed version ofIList<T>
, let's sayIList<string>
.The second one is the generic definition of
IList<T>
without a type forT
.That makes the two interfaces different. There are not the same, since the first is a concrete version of the second.