0

I'm confused... I have no idea why this particular problem is occurring and I was wondering if someone could shed some light on the subject. I'm doing some reflection operations which requires a lot of Type comparisons - as such I'm storing some information with the "Type" as the key...

However, it seems two of my types, even though they seem superficially the same, are not actually the same as it's throwing a "Key Not Found" exception when I try to look it up.

Here's a screenshot of my inspector:

enter image description here

Is there some detail about comparing underlying types I might be missing?

EDIT: In accordance with Mr. Skeet's request, here is the underlying class that is supposed to generate the entire type tree of an object. It's somewhat messy, as I've been futzing with it too much - you can see here that the same "Type" object is added to both "myType" and "myTypeTypes" - so I have no idea why they're suddenly becoming different objects...

 public class TypeTree
    {
        private Type original;
        private TypeTree subTree;
        private Dictionary<Type, List<Type>> subTreeTypes = new Dictionary<Type, List<Type>>();
        private List<Type> myTypes = new List<Type>();
        private Dictionary<Type, List<Type>> myTypeTypes = new Dictionary<Type, List<Type>>();


        public TypeTree(Type Next)
        {
            original = Next;
            if (Next.IsGenericType)
            {
                myTypes.Add(Next.GetGenericTypeDefinition());
                Type[] genTypes = Next.GetGenericArguments();
                subTreeTypes.Add(Next.GetGenericTypeDefinition(), new List<Type>(genTypes));
            }
            else
            {
                myTypes.Add(Next);

            }

            Type[] lis = Next.GetInterfaces();
            foreach (var v in lis)
            {                    
                if (v.IsGenericType)
                {
                    Type genType = v.GetGenericTypeDefinition();
                    myTypes.Add(genType);                       
                    Type[] genTypes = v.GetGenericArguments();
                    myTypeTypes.Add(genType, new List<Type>());
                    myTypeTypes[genType].AddRange(genTypes);
                }
                else
                {
                    myTypes.Add(v);
                }
            }
            try
            {
                subTree = new TypeTree(Next.BaseType, myTypes, myTypeTypes, subTreeTypes, Next);
            }
            catch (NullReferenceException ex)
            {

            }
        }

        private TypeTree(Type Next, List<Type> MyList, Dictionary<Type, List<Type>> MyTypeTypes, Dictionary<Type, List<Type>> SubTreeTypes, Type Original)
        {

            if (Next.IsGenericType || Next.IsGenericTypeDefinition)
            {
                MyList.Add(Next.GetGenericTypeDefinition());
                Type[] genTypes = Next.GetGenericArguments();
                SubTreeTypes.Add(Next.GetGenericTypeDefinition(), new List<Type>(genTypes));
            }
            else
            {
                MyList.Add(Next);
                SubTreeTypes.Add(Next, new List<Type>(Original.GetGenericArguments()));
            }
            Type[] lis = Next.GetInterfaces();
            foreach (var v in lis)
            {
                if (v.IsGenericType)
                {
                    Type genType = v.GetGenericTypeDefinition();
                    MyList.Add(genType);
                    Type[] genTypes = v.GetGenericArguments();                        
                    MyTypeTypes.Add(genType, new List<Type>());
                    MyTypeTypes[genType].AddRange(genTypes);
                }
                else
                {
                    myTypes.Add(v);
                }
            }
            try
            {
                subTree = new TypeTree(Next.BaseType, myTypes, MyTypeTypes, SubTreeTypes, Original);
            }
            catch (NullReferenceException ex)
            {

            }
        }

        public bool ReturnBestType(Dictionary<Type, MethodInfo> Search, ref MethodInfo SelectedMethod)
        {
            bool ret = false;
            for (int i = 0; i < myTypes.Count; i++)
            {
                if (Search.ContainsKey(myTypes[i]))
                {
                    if (myTypes[i].IsGenericTypeDefinition)
                    { 
                        List<Type> Args = new List<Type>();
                        Args.Add(original);
                        Args.AddRange(myTypeTypes[myTypes[i]].ToArray());

                        MethodInfo mi = Search[myTypes[i]].MakeGenericMethod(Args.ToArray()); 
                        SelectedMethod = mi;
                        return true;
                    }
                    else
                    {
                        SelectedMethod = Search[myTypes[i]]; 
                        ret = true;
                        break;
                    }
                }
            }

            return ret;
        }
    }
ThisHandleNotInUse
  • 1,135
  • 1
  • 10
  • 23
  • 2
    It would be *much* more helpful if you'd post a short but complete program demonstrating the problem, instead of a screenshot. – Jon Skeet Aug 06 '15 at 14:05
  • (My guess is that it's due to the `T`s being different, btw. The interfaces implemented by `List` and `LinkedList` each refer to a type parameter `T`, but it's the type parameter "owned" by the concrete class, so that may well explain the difference...) – Jon Skeet Aug 06 '15 at 14:07
  • @JonSkeet I've added the entire class to the post. It is supposed to elucidate the entire inheritance hierarchy of any Type to determine whether or not a passed in dictionary of generic methods has a matching return type. – ThisHandleNotInUse Aug 06 '15 at 14:21
  • 1
    I didn't ask for the entire class. I asked for a short but complete program demonstrating the problem. I'm sure you could have reduced that to a shorter example... – Jon Skeet Aug 06 '15 at 14:22
  • @JonSkeet I'm sorry, you're very helpful on this site, but apparently it was throwing the exception on a different line. I have no idea why it threw the exception on that line a few times but I guess I must have fixed it somehow and not noticed the exception was on another line or something. Anyway, this is working as intended and my question was useless. – ThisHandleNotInUse Aug 06 '15 at 14:45

2 Answers2

1

The closed generic types is different for the each specialization type

typeof(List<int>) != typeof(List<bool>)

class MyList : List<int> {}
typeof(MyList) != typeof(List<int>)

You should check the booth a base generic type and generic parameter types

You can investigate this How to get base class's generic type parameter

Community
  • 1
  • 1
Viacheslav Smityukh
  • 5,652
  • 4
  • 24
  • 42
1

I suspect you're running into a problem due to the T in ICollection<T> being different in each case. Here's a short but complete example:

using System;

interface IFoo<T> {}

public class Foo1<T> : IFoo<T> {}
public class Foo2<T> : IFoo<T> {}

class Test
{
    static void Main()
    {
        var type1 = typeof(Foo1<>).GetInterfaces()[0];
        var type2 = typeof(Foo2<>).GetInterfaces()[0];

        Console.WriteLine(type1);
        Console.WriteLine(type2);
        Console.WriteLine(type1.Equals(type2));
    }
}

Output:

IFoo`1[T]
IFoo`1[T]
False

Now you can use Type.GetGenericTypeDefinition() to effectively remove the T in each case:

Console.WriteLine(type1.GetGenericTypeDefinition()
    .Equals(type2.GetGenericTypeDefinition())); // True

... but it's unclear whether that helps in your real use case.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • I am using that... that's why this is so confusing... In fact I added the exact same variable to both "myTypes" and "myTypeTypes..." This is really bizarre - maybe I'm too tired to be looking at this. – ThisHandleNotInUse Aug 06 '15 at 14:30
  • 1
    @ThisHandleNotInUse: If you could reduce your sample code to a short but complete example (it's neither at the moment) ideally following .NET naming conventions, I'd be able to help you diagnose the problem better... hint hint. – Jon Skeet Aug 06 '15 at 14:34
  • You know what, I just stepped through it slowly again and it's throwing an exception on a completely different line... I stepped through it several times before that and it was throwing the exception on that line, so I guess, like I said, I'm too tired to be looking at this. My apologies for wasting time. – ThisHandleNotInUse Aug 06 '15 at 14:36