tags:

views:

236

answers:

3

The code segment below prints out "The types ARE NOT the same.". Why? I am aware of the fact that using interfaceOnMyType.GetGenericTypeDefinition() will solve the problem, but why should I have to do that?

class Program
{
    static void Main(string[] args)
    {
     var myType = typeof(Baz<>);
     var interfaceOnMyType = myType.GetInterfaces().SingleOrDefault();
     var exactType = typeof(IBar<>);
     if (exactType == interfaceOnMyType)
     {
      Console.WriteLine("The types ARE the same.");
     }
     else
     {
      Console.WriteLine("The types ARE NOT the same.");
     }
     Console.ReadLine();
    }
}

interface IBar<T>
{
}

class Baz<T> : IBar<T>
{
}
+2  A: 
interfaceOnMyType.GetGenericTypeDefinition()

returns you the closed constructed type of the interface which is different from the type returned from

typeof(IBar<>)

Here is the MSDN article on GetGenericTypeDefinition, and here is a good quote from it explaining how it works:

Given a Type object representing this constructed type, the GetGenericTypeDefinition method returns the generic type definition.


Edit (the answer above is correct in some cases but wrong in this one):

I think I may have found it now. The reason that the type comparison is failing is because the Type returned from myType.GetInterfaces() is close to but not identical to the type of the interface itself.

According to MSDN:

If you use the BaseType property to obtain the base type of Derived, the FullName property of the resulting Type object returns null (Nothing in Visual Basic). To get a non-null FullName, you can use the GetGenericTypeDefinition method to get the generic type definition.

So I think this is the problem you are seeing. Since base interfaces are retrieved via GetInterfaces any type retrieved by that call will not have a FullName (source). Since it does not have a FullName the types will fail in comparison.

What I orginally wrote would be true if you were comparing the constructed type which you are not. So unfortunately my first answer is dead wrong - I have left it so that the comments left will make sense.

Andrew Hare
Nope, they are the same - try it.
Eric Smith
A: 

The reason is that interfaceOnMyType.IsGenericTypeDefinition returns false, whilst myType.IsGenericTypeDefinition and exactType.IsGenericTypeDefinition both return true. That is, just because you're retrieving a non-constructed generic type from a generic type definition does not mean that the type you retrieve is itself a generic type definition.

Eric Smith
A: 

Try the following

            Console.WriteLine("{0}", (null != exactType.FullName) ? exactType.FullName : "null");
            Console.WriteLine("{0}", (null != interfaceOnMyType.FullName) ? interfaceOnMyType.FullName : "null");

The output is:

test.Program+IBar`1
null

This supports the findings posted here by Andrew Hare.

ILoveFortran