Type.IsSubclssOf and Type.IsAssignableFrom
Type
这个类有两个非常有用的方法: IsSubClassOf
和IsAssignableFrom
。允许调用者在运行时确定任意两个类型是否有继承关系。
IsSubClassOf
微软MSDN
文档上对IsSubClassOf
的描述如下:
Determines whether the class represented by the current Type derives from the class represented by the specified Type.
确定当前类是否由指定的类型派生而来
下面来看一些测试代码:
public class ClassA { }
public class ClassB : ClassA { }
public class ClassC : ClassB { }
...
Console.WriteLine(typeof(ClassB).IsSubclassOf(typeof(ClassA))); // True
Console.WriteLine(typeof(ClassB).IsSubclassOf(typeof(ClassB))); // False
Console.WriteLine(typeof(ClassB).IsSubclassOf(typeof(ClassC))); // False
Console.WriteLine(typeof(ClassC).IsSubclassOf(typeof(ClassA))); // True
Console.WriteLine(typeof(ClassC).IsSubclassOf(typeof(ClassB))); // True
这个方法不能用于判断是否是某个接口
The IsSubclassOf method cannot be used to determine whether an interface derives from another interface, or whether a class implements an interface.
IsSubClassOf 这个方法不能用来确定一个接口继承自另一个接口,也不能确定一个类实现了某一个接口
例如:
public interface ID { }
public interface IE : ID { }
public class ClassD : ID { }
...
Console.WriteLine(typeof(ClassD).IsSubclassOf(typeof(ID))); // False
Console.WriteLine(typeof(IE).IsSubclassOf(typeof(ID))); // False
对于泛型类又是怎么样的呢,看下面的示例:
public class ClassF<T> { }
public class ClassG<T> : ClassF<T> { }
public class ClassH : ClassF<int> { }
// no type constraint, no good
Console.WriteLine(typeof(ClassG<>).IsSubclassOf(typeof(ClassF<>))); // False
// no covariance support here
Console.WriteLine(typeof(string).IsSubclassOf(typeof(object))); // True
Console.WriteLine(typeof(ClassG<string>).IsSubclassOf(typeof(ClassF<object>))); // False
// type constraint has to match
Console.WriteLine(typeof(ClassG<int>).IsSubclassOf(typeof(ClassF<int>))); // True
Console.WriteLine(typeof(ClassH).IsSubclassOf(typeof(ClassF<int>))); // True
Console.WriteLine(typeof(ClassH).IsSubclassOf(typeof(ClassF<long>))); // False
IsAssignableFrom
MSDN
上的解释如下:
Determines whether an instance of the current Type can be assigned from an instance of the specified Type.
确定是否可以将指定的类型实例赋值给当前类型的实例
IsAssignableFrom
方法和is
操作符的工作方式基本相同,它做了一个简单的赋值兼容性测试,检查a
类型的变量是否可以赋值给b
类型的变量。与IsSubClassOf
方法不同的是,这个方法适用于接口之间的检查。记住:如果typeof(B).IsSubclassOf(typeof(A))
为true
,那么typeof(A).IsAssignableFrom(typeof(B))
也为true
。
Console.WriteLine(typeof(IA).IsAssignableFrom(typeof(IB))); // True
Console.WriteLine(typeof(IA).IsAssignableFrom(typeof(IA))); // True
Console.WriteLine(typeof(IB).IsAssignableFrom(typeof(IA))); // False
Console.WriteLine(typeof(IA).IsAssignableFrom(typeof(ClassA))); // True
Console.WriteLine(typeof(ClassA).IsAssignableFrom(typeof(ClassB))); // True
同样的,对于泛型之间的判断
// no type constraint, still no good
Console.WriteLine(typeof(ClassF<>).IsAssignableFrom(typeof(ClassG<>))); // False
// note: whilst you can't specify generic variance on the class definition you can do it on the
// interface, e.g. IEnumerable<out T>, so we're able to do the following test
Console.WriteLine(typeof(object).IsAssignableFrom(typeof(string))); // True
Console.WriteLine(typeof(IEnumerable<object>).IsAssignableFrom(typeof(IEnumerable<string>))); // True
性能开销
通常,反射对于性能来说都是一项昂贵的开销,如果必须在代码中执行大量反射,应该要注意潜在的性能问题。