如何比较两个通用" Type"变量?

时间:2015-08-06 14:03:36

标签: c# generics reflection types key

我很困惑......我不知道为什么会出现这个特殊问题,我想知道是否有人可以对这个问题有所了解。我正在进行一些需要大量类型比较的反射操作 - 因此我会使用" Type"存储一些信息。作为关键...

然而,看起来我的两种类型,即使它们看起来表面相同,但实际上并不是一样的,因为它没有发现" Key Not Found"我尝试查找时例外。

这是我的检查员的屏幕截图:

enter image description here

是否有一些关于比较我可能缺少的基础类型的细节?

编辑:根据Skeet先生的请求,这里是应该生成对象的整个类型树的基础类。它有点凌乱,因为我已经过多地使用它 - 你可以在这里看到相同的" Type"对象被添加到" myType"和" myTypeTypes" - 所以我不知道他们为什么突然变成不同的对象......

 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;
        }
    }

2 个答案:

答案 0 :(得分:1)

每种专业化类型的封闭泛型类型不同

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

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

您应该检查展位的基本通用类型和通用参数类型

您可以调查此How to get base class's generic type parameter

答案 1 :(得分:1)

由于T中的ICollection<T>在每种情况下都不同,我怀疑您遇到了问题。这是一个简短而完整的例子:

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));
    }
}

输出:

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

现在,您可以使用Type.GetGenericTypeDefinition()在每种情况下有效删除T

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

...但目前还不清楚这对您的实际用例是否有帮助。