31

一位同事今天问了我一个有趣的问题——C# 关键字/运算符“is”是否被认为是反射?

object tmp = "a string";
if(tmp is String)
{
}

这个操作符是如何在幕后实现的?它需要反思还是自省?或者由于语言的强类型特性,对象的类型是否可以作为内存中对象的顶级属性立即访问?

MSDN指出:

请注意,is 运算符仅考虑引用转换、装箱转换和拆箱转换。is 运算符不考虑其他转换,例如用户定义的转换。

考虑装箱和未装箱转换的能力对我来说似乎意味着某种内省。

4

3 回答 3

39

参考 ECMA-335is操作员生成isinst对象模型 IL 指令(Partition III §4.6),它是基本指令集的一部分,而不是反射库的一部分(Partition IV §5.5)。

编辑:is与反射库相比,该运算符非常有效。您可以通过反射更慢地执行基本相同的测试:

typeof(T).IsAssignableFrom(obj.GetType())

编辑2:您对castclassandisinst指令的效率不正确(您现在已经从帖子中编辑了)。它们在任何实际的 VM 实现中都经过高度优化。唯一真正涉及的性能问题是castclass引发异常的可能性,您可以通过使用 C#as运算符和测试null(对于引用类型)或is运算符后跟强制转换(对于值类型)来避免这种情况。

于 2009-07-15T21:09:22.033 回答
5

运算符本质上is确定是否可以进行强制转换,但不是在不可能进行强制转换时抛出异常,而是返回false。如果您考虑投射反射,那么这也是反射。

编辑:

经过一些研究,我发现在 IL påcastclass指令中执行转换,而is运算符映射到isinst指令。FxCop 有一条规则,如果您正在执行不必要的强制转换,请先使用该指令isinst,然后再使用该castclass指令来警告您。尽管这些操作是高效的,但它们仍然存在性能成本。

于 2009-07-15T20:59:45.203 回答
1

其他语言具有足以支持动态转换的运行时间信息,但没有任何东西可以描述为反射(C++ 就是一个明显的例子)。

因此,反射指的是除了发现对象类型之外的附加功能。例如,“反映”一个对象意味着能够行走其成员。

于 2009-07-15T21:03:12.870 回答