要在c#中检查一个类型是否是另一个类型的子类,很简单:

typeof (SubClass).IsSubclassOf(typeof (BaseClass)); // returns true

然而,这将失败:

typeof (BaseClass).IsSubclassOf(typeof (BaseClass)); // returns false

有什么方法可以在不使用或操作符或扩展方法的情况下检查类型是否是基类本身的子类或?


当前回答

很明显,没有。

以下是选项:

使用类型。IsSubclassOf 使用类型。IsAssignableFrom Is和as

类型。IsSubclassOf

正如你已经发现的,如果两种类型相同,这将不起作用,下面是一个示例LINQPad程序,演示:

void Main()
{
    typeof(Derived).IsSubclassOf(typeof(Base)).Dump();
    typeof(Base).IsSubclassOf(typeof(Base)).Dump();
}

public class Base { }
public class Derived : Base { }

输出:

True
False

这表明Derived是Base的子类,但Baseis(显然)不是它本身的子类。

类型。IsAssignableFrom

这可以回答你的问题,但也会给你假阳性。正如Eric Lippert在评论中指出的,虽然该方法确实会对上述两个问题返回True,但它也会对这些问题返回True,这可能是你不想要的:

void Main()
{
    typeof(Base).IsAssignableFrom(typeof(Derived)).Dump();
    typeof(Base).IsAssignableFrom(typeof(Base)).Dump();
    typeof(int[]).IsAssignableFrom(typeof(uint[])).Dump();
}

public class Base { }
public class Derived : Base { }

这里你会得到以下输出:

True
True
True

最后一个True表示,如果方法只回答了所问的问题,uint[]继承了int[],或者它们是相同的类型,但显然不是这样。

所以IsAssignableFrom也不完全正确。

Is和as

“问题”是,并且在您的问题的上下文中是,它们将要求您操作对象,并直接在代码中编写其中一个类型,而不是使用Type对象。

换句话说,这将不会编译:

SubClass is BaseClass
^--+---^
   |
   +-- need object reference here

这个也不会:

typeof(SubClass) is typeof(BaseClass)
                    ^-------+-------^
                            |
                            +-- need type name here, not Type object

这个也不会:

typeof(SubClass) is BaseClass
^------+-------^
       |
       +-- this returns a Type object, And "System.Type" does not
           inherit from BaseClass

结论

虽然上述方法可能适合你的需求,但对你的问题(在我看来)唯一正确的答案是你需要额外检查:

typeof(Derived).IsSubclassOf(typeof(Base)) || typeof(Derived) == typeof(Base);

当然,这在方法中更有意义:

public bool IsSameOrSubclass(Type potentialBase, Type potentialDescendant)
{
    return potentialDescendant.IsSubclassOf(potentialBase)
           || potentialDescendant == potentialBase;
}

其他回答

typeof(BaseClass).IsAssignableFrom(unknownType);

你应该尝试使用Type。IsAssignableFrom代替。

很明显,没有。

以下是选项:

使用类型。IsSubclassOf 使用类型。IsAssignableFrom Is和as

类型。IsSubclassOf

正如你已经发现的,如果两种类型相同,这将不起作用,下面是一个示例LINQPad程序,演示:

void Main()
{
    typeof(Derived).IsSubclassOf(typeof(Base)).Dump();
    typeof(Base).IsSubclassOf(typeof(Base)).Dump();
}

public class Base { }
public class Derived : Base { }

输出:

True
False

这表明Derived是Base的子类,但Baseis(显然)不是它本身的子类。

类型。IsAssignableFrom

这可以回答你的问题,但也会给你假阳性。正如Eric Lippert在评论中指出的,虽然该方法确实会对上述两个问题返回True,但它也会对这些问题返回True,这可能是你不想要的:

void Main()
{
    typeof(Base).IsAssignableFrom(typeof(Derived)).Dump();
    typeof(Base).IsAssignableFrom(typeof(Base)).Dump();
    typeof(int[]).IsAssignableFrom(typeof(uint[])).Dump();
}

public class Base { }
public class Derived : Base { }

这里你会得到以下输出:

True
True
True

最后一个True表示,如果方法只回答了所问的问题,uint[]继承了int[],或者它们是相同的类型,但显然不是这样。

所以IsAssignableFrom也不完全正确。

Is和as

“问题”是,并且在您的问题的上下文中是,它们将要求您操作对象,并直接在代码中编写其中一个类型,而不是使用Type对象。

换句话说,这将不会编译:

SubClass is BaseClass
^--+---^
   |
   +-- need object reference here

这个也不会:

typeof(SubClass) is typeof(BaseClass)
                    ^-------+-------^
                            |
                            +-- need type name here, not Type object

这个也不会:

typeof(SubClass) is BaseClass
^------+-------^
       |
       +-- this returns a Type object, And "System.Type" does not
           inherit from BaseClass

结论

虽然上述方法可能适合你的需求,但对你的问题(在我看来)唯一正确的答案是你需要额外检查:

typeof(Derived).IsSubclassOf(typeof(Base)) || typeof(Derived) == typeof(Base);

当然,这在方法中更有意义:

public bool IsSameOrSubclass(Type potentialBase, Type potentialDescendant)
{
    return potentialDescendant.IsSubclassOf(potentialBase)
           || potentialDescendant == potentialBase;
}

如果你试图在Xamarin Forms PCL项目中做到这一点,上面的解决方案使用IsAssignableFrom会给出一个错误:

错误:“类型”不包含“IsAssignableFrom”的定义 没有扩展方法'IsAssignableFrom'接受的第一个参数 类型'类型'可以找到(你是否缺少一个使用指令或一个 装配参考?)

因为IsAssignableFrom请求TypeInfo对象。 您可以使用System中的GetTypeInfo()方法。反射:

typeof(BaseClass).GetTypeInfo()。IsAssignableFrom(typeof(unknownType).获取类型信息())

我张贴这个答案,希望有人能和我分享这是否是一个坏主意,以及为什么这是一个坏主意。在我的应用程序中,我有一个类型的属性,我想检查,以确保它是typeof(a)或typeof(B),其中B是从a派生的任何类,所以我的代码:

public class A
{
}

public class B : A
{
}

public class MyClass
{
    private Type _helperType;
    public Type HelperType
    {
        get { return _helperType; }
        set 
        {
            var testInstance = (A)Activator.CreateInstance(value);
            if (testInstance==null)
                throw new InvalidCastException("HelperType must be derived from A");
            _helperType = value;
        }
    }
}

我觉得我可能有点天真,所以任何反馈都会受到欢迎。