Common strange behavior

I met strange generic behavior. Below is the code I'm using for testing.

public static class Program { public static void Main() { Type listClassType = typeof(List<int>).GetGenericTypeDefinition(); Type listInterfaceType = listClassType.GetInterfaces()[0]; Console.WriteLine(listClassType.GetGenericArguments()[0].DeclaringType); Console.WriteLine(listInterfaceType.GetGenericArguments()[0].DeclaringType); } } 

Output:

 System.Collections.Generic.List`1[T] System.Collections.Generic.List`1[T] 

It was very strange to me that the second call to Console.WriteLine displays the class, not the interface, because I use a generic type definition. Is this the right behavior?

I am trying to implement generic type inference in my compiler. Suppose I have the code below.

 public static class GenericClass { public static void GenericMethod<TMethodParam>(IList<TMethodParam> list) { } } 

And I want to call this method as follows:

 GenericClass.GenericMethod(new List<int>()); 

To check the possibility of output, I need to compare the type in the method signature and the type of the arguments passed. But the code below returns false.

 typeof(GenericClass).GetMethods()[0].GetParameters()[0].ParameterType == listInterfaceType; 

Should I always use Type.GetGenericTypeDefinition for such comparisons?

+6
source share
2 answers

You are misleading two different types, which are both called T. Think of it this way:

 interface IFoo<TIFOO> { } class Foo<TFOO> : IFoo<TFOO> {} 

OK, what is the definition of the type type Foo<int> ? This is Foo<TFOO> .

What is the interface implemented by Foo<TFOO> ? This is IFoo<TFOO> .

What is an argument of type Foo<TFOO> ? Obviously TFOO .

What type is declared TFOO ? Foo<TFOO> declared.

What is an argument of type IFoo<TFOO> ? Obviously TFOO , not TIFOO .

What type is declared TFOO ? Foo<TFOO> announced this. not IFoo<TFOO> . TFOO comes from Foo .

Make sense?

+15
source

Adding a second answer because you added a second question:

I am trying to implement generic type inference in my compiler ...

And so, I assume that you are using reflection to create a compiler. This may not be a good idea. Reflection is now much more effective than it was in the early days, but it is still heavy compared to working with tokens. And reflection radiation cannot emit all kinds of topology types; it got messed up in some scenarios related to nested structure types.

Instead, I would rather use CCI. We used a modified version of CCI for Roslyn.

the code below returns false.

 typeof(GenericClass).GetMethods()[0].GetParameters()[0].ParameterType == listInterfaceType 

It is right. The parameter type is IList<TMethodParam> , and listInterfaceType is IList<T> , where T is the general parameter type declared by List<T> and not the general parameter type declared by IList<T> . These are all different types.

Should I always use Type.GetGenericTypeDefinition for such comparisons?

If you want to see if two common types are constructs of the same generic type, yes. If this is not what you want to check, then no.

This type system is complex, so be very careful.

This is another reason to go using a token-based approach rather than a reflection-based approach. When you have tokens in hand, it is much easier to distinguish between a TypeDef and a TypeRef .

+2
source

All Articles