如何检查一个types是一个子types还是一个对象的types?
要检查一个types是否是C#中另一个types的子类,很容易:
typeof (SubClass).IsSubclassOf(typeof (BaseClass)); // returns true
但是,这将失败:
typeof (BaseClass).IsSubclassOf(typeof (BaseClass)); // returns false
有没有什么办法来检查一个types是否是基类自身的子类,不使用OR
运算符或使用扩展方法?
显然,不。
这里是选项:
- 使用Type.IsSubclassOf
- 使用Type.IsAssignableFrom
-
is
和
Type.IsSubclassOf
正如你已经发现的,如果这两种types是相同的,这将不起作用,下面是一个示例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
(显然)不是它自己的子类。
Type.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[]
inheritance,或者它们是相同的types,显然不是这种情况。
所以IsAssignableFrom
也不完全正确。
is
和
与问题相关的“问题”在于,它们将要求您对对象进行操作,并直接在代码中编写其中一种types,而不能使用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来代替。
我发布这个答案,希望有人与我分享,如果为什么这将是一个坏主意。 在我的应用程序中,我有一个Type的属性,我想检查它是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; } } }
我觉得我可能会有点天真,所以任何反馈都会受到欢迎。