1(.GetType()
将返回调用它的对象的运行时类型, 这是继承层次结构中最具体的类型。您可以使用typeof()
获取类名Type
的函数
2(is运算符将检查左侧对象的类型是否 是 的子类型,或与右侧指定的类型相同
3( 鉴于您只需要检查对象的最特定类型,并且不需要强制转换,前者 (1( 是否比后者 (2( 快得多?
4(is
运算符是否实际执行转换并检查 null,或者 此行为已在 C Sharp 的更高版本中进行了修改?
typeof(x)
是获取文本类型的Type-Object,如typeof(int)
。这是一个运行时常量。
对于object.GetType()
,您需要一个对象实例。
if (x is IList)
is 运算符执行强制转换,但如果 x 为 null 或不兼容的类型,则在成功时返回 bool 或 false。 跟
if (x is IList list)
您可以同时进行布尔测试和强制转换。
谈论性能是没有意义的,因为这是完全不同的操作。
如果要获取对象实例的类型object.GetType()
这是唯一的选择,但您可以再次测试它,例如
x.GetType() == typeof(List)
虽然你可以确定
x.GetType() == typeof(IList)
将始终为 false,因为 GetType 永远不会返回接口的类型。 对于此测试,您需要
typeof(IList).IsAssignableFrom(x.GetType());
前 4 个(,因为它更简单。is
运算符与as
运算符一起实现。
x is C
与
x as C != null
对于来源,您可以查看神话般的Eric Lippert的博客。目前(提交 e09c42a(,Roslyn 编译器将两者转换为
isinst C
ldnull
cgt.un
其中isinst
是尝试将x
转换为C
并将强制转换的引用保留在堆栈顶部的神奇指令,如果失败,则null
。剩下的两个指令是检查null
。
至于性能,很难肯定地说。从理论上讲,使用is
进行检查应该更快,因为它是一个内置的 CLR 指令,针对它的功能进行了大量优化,而另一个检查必须调用三种方法,即GetType()
、GetTypeFromHandle(RuntimeTypeHandle)
和Type
上的相等。还有与调用GetType()
有关的标准检查空和抛出 NRE 。一个非常粗略的基准支持这个假设:链接到DotNetFiddle。如果有人愿意执行更复杂的基准测试,请继续。
显然,我可以想象您的继承层次结构如此深入和复杂,以至于is
检查所需的时间将超过GetType()
的任何开销。随意将我的基准测试子类型到 C100,并检查这是否足够:)
编辑: 我想我应该补充一点,这个讨论纯粹是理论上的。在生产代码中,您应该使用x is C
,因为它简洁且更健壮,因为它检查整个层次结构的子类型。如果您有一个检查给定实例类型的热路径,并且您知道层次结构是扁平的,则可能应该重新设计系统以避免该检查,而不是丑化代码以挤出一些性能。