检查实例是否继承自C#中类的泛型或非泛型版本

时间:2016-06-06 09:10:32

标签: c# .net generics inheritance casting

所以我有这样的继承链:

class a : {}
class a<T> : {}
class b: a<int> {}
class c: a {}

我需要检查实例(让我们说var inst = new b())是继承自a<>还是仅来自a

但是,标准IsAssignableFromIsSubclassOfIsInstanceOfTypeis都不合适。

这样做的正确方法是什么?

UPD1:继承链可能超过1级

6 个答案:

答案 0 :(得分:3)

b类的实例不是来自a<T>,而是来自a<int>,两者是不同的类型。

var type = inst.GetType();
var result = false;

while (type != typeof(object))
{
    type = type.BaseType;
    if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(a<>))
    {
        result = true;
        break;
    }
}

//check result

答案 1 :(得分:1)

b 继承自a<>,它继承自a<int>。但是,您可以通过反射检查基类的泛型类型定义是否为a<>

type t = typeof(b).BaseType;
return t.IsGenericType && t.GetGenericTypeDefinition() == typeof(a<>);

答案 2 :(得分:1)

使用您的更新(更多继承级别),您可以拥有:

public static bool IsGenericA(object instance)
{
    Type t = instance.GetType();
    while(t.BaseType != null && t.BaseType != typeof(object))
      t = t.BaseType;
    return t.IsGenericType && t.GetGenericTypeDefinition() == typeof(a<>);
}

public static bool IsNonGenericA(object instance)
{
    Type t = instance.GetType();
    while(t.BaseType != null && t.BaseType != typeof(object))
      t = t.BaseType;
    return t == typeof(a);
}

See it in action in this fiddle

只要基数为aa<something>

,就可以适用于任何级别

答案 3 :(得分:1)

假设你有这个层次结构:

class a { }
class a<T> : a { }
class b : a<int> { }
class c : a { }

您需要探索继承树以获取基类泛型类型并测试其泛型类型定义。但是,如果您正在寻找一些通用的解决方案,则必须考虑接口实现案例。

,例如,如果您的层次结构将被重写为:

interface a { }
interface a<T> : a { }
class b : a<int> { }
class c : a { }

这将“中断”继承树遍历,因为b的基本类型将是System.Object而不是a<T>。也就是说,继承和接口实现是两回事。

我会这样实现它:

internal static class TypeExtensions
{
    private static bool IsInheritedFromGenericTypeDefinition(Type type, Type baseType)
    {
        do
        {
            if (type.IsGenericType && type.GetGenericTypeDefinition() == baseType)
                return true;

            type = type.BaseType;
        }
        while (type != null);

        return false;
    }

    public static bool IsInheritedFrom(this Type type, Type baseType)
    {
        if (baseType.IsGenericTypeDefinition)
        {
            if (!type.IsInterface && baseType.IsInterface)
            {
                do
                {
                    // since baseType is an interface, and source type is not,
                    // we can't test inheritance tree anymore;
                    // instead, we have to obtain implemented interfaces and test them
                    var implementedInterfaces = type.GetInterfaces();
                    if (implementedInterfaces.Any(intf => IsInheritedFromGenericTypeDefinition(intf, baseType)))
                        return true;

                    type = type.BaseType;
                }
                while (type != null);

                return false;
            }
            else
                return IsInheritedFromGenericTypeDefinition(type, baseType);
        }

        return baseType.IsAssignableFrom(type);
    }
}

结果:

  

a - &gt;一个&LT;&GT; =真

     

b - &gt;一个&LT;&GT; =真实   b - &gt; a =真实   b - &gt; a =真

     

c - &gt; a =真实   c - &gt;一个&LT;&GT; =假

答案 4 :(得分:0)

typeOf()怎么样?您可以使用此

获取父类

答案 5 :(得分:0)

class a : {}
class a<T> : {}

对不起,但在C#aa<T>完全不同。他们都以字母a开头的事实是巧合。

因此,为了区分,您可以使用is operator

 if (inst is a)
 {
    // derived from a
 }
 else 
 {
    // not derived from a
 }