在C#中检查一个类型是否是另一个类型的子类很容易:
typeof (SubClass).IsSubclassOf(typeof (BaseClass)); // returns true
然而,这会失败:
typeof (BaseClass).IsSubclassOf(typeof (BaseClass)); // returns false
有没有一种方法可以在不使用OR运算符或扩展方法的情况下检查一个类型是否是子类或基类本身?
在C#中检查一个类型是否是另一个类型的子类很容易:
typeof (SubClass).IsSubclassOf(typeof (BaseClass)); // returns true
然而,这会失败:
typeof (BaseClass).IsSubclassOf(typeof (BaseClass)); // returns false
有没有一种方法可以在不使用OR运算符或扩展方法的情况下检查一个类型是否是子类或基类本身?
显然不行。
以下是选项:
is
和as
正如你已经发现的那样,如果两个类型相同,这种方法将不起作用。以下是一个演示的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
的一个子类,但Base
(显然)不是它本身的子类。
虽然这种方法将会回答你的具体问题,但也会给你返回错误的结果。正如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
在你的问题的背景下,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);
IsAssignableFrom
会出现错误:IsAssignableFrom
需要一个TypeInfo
对象。您可以使用System.Reflection
的GetTypeInfo()
方法:
typeof(BaseClass).GetTypeInfo().IsAssignableFrom(typeof(unknownType).GetTypeInfo())
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;
}
}
}
我觉得我可能有点天真,所以欢迎任何反馈。
IsInstanceOfType
应该如何适配这个场景? - Lennarttypeof(Test).GetInterfaces().Contains(typeof(ITest))
来测试一个类是否实现了一个接口,或者使用typeof(ITest).IsAssignableFrom(typeof(Test))
。 - Lasse V. KarlsenIsAssignableFrom
回答的问题与“一个类型是否是另一个类型的子类型”这种类型的问题不同。它试图回答的是a = b
是否有效。我已经有一段时间没有看过这些东西了,也不知道为什么在这里IsAssignableFrom返回true
,因为实际上你不能直接将uint[]
数组赋值给int[]
变量,反之亦然,但我猜可能在某个地方可以进行一些强制转换。无论如何,int[]
并不是uint[]
的子类型,反之亦然,所以使用IsAssignableFrom
来回答这个问题是不正确的。不过,对于你的需求来说可能已经足够接近了。 - undefined