【问题标题】:C# "is" operator - is that reflection?C# "is" 运算符 - 那是反射吗?
【发布时间】:2010-11-11 03:57:08
【问题描述】:

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

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

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

MSDN 声明:

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

在我看来,考虑装箱和未装箱转换的能力似乎暗示了某种自省。

【问题讨论】:

标签: c# .net reflection introspection typing


【解决方案1】:

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

编辑:

经过一些研究,我发现在 IL på castclass 指令中执行转换,而 is 运算符映射到 isinst 指令。 FxCop 有一个rule,它会在您进行不必要的强制转换时警告您,首先使用isinst,然后使用castclass 指令。尽管操作很高效,但它们仍然存在性能成本。

【讨论】:

  • 'is' 运算符返回真/假而不是空值。
  • 我认为您正在考虑“as”运算符
  • 您所描述的是“as”运算符。 'is' 操作符本质上是相同的操作,只是返回值不同。
  • 你是对的,我在回答中混合了“is”和“as”。我已经纠正了我的错误。
【解决方案2】:

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

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

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

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

【讨论】:

  • 我没有编辑任何内容,但也许我应该澄清一下我所说的“昂贵”是什么意思。我对 IL 效率知之甚少,但如果您创建的代码同时发出 isinst 和 castclass 指令,FxCop 会发出警告,因为他们认为它效率低下或“昂贵”。
  • 正如我在第二次编辑中提到的,您应该使用 as 后跟 null 检查引用类型。您改为使用 is 和演员表,这是 FxCop 提醒您的。
  • 值得一提的是,在 Compact Framework 上,需要显式检查 RTTI 的 IL(例如 isinstcastclass)与反射一样慢,而 callvirt 则经过高度优化。道德:尽量避免使用虚拟/抽象方法可以工作的类型案例构造。
  • @SamHarwell 指向 ECMA-335 的链接已损坏,您知道更新版本吗?
【解决方案3】:

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

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

【讨论】:

  • 如果说反射解析类的成员而不是对象的成员会正确,因为您不需要有一个活动的实例。反射还可以“发现”您在程序集中拥有哪些类,而不仅仅是类的成员和其他信息。
  • @Danny Varod - 并非所有语言都有类或程序集。
  • C++ 有类和库,Java 有类和包。面向对象编程确实定义了对象和类之间的区别。
  • 另外,C++ 不能有反射——因为二进制文件中没有嵌入所需的信息。 - 这就是为什么你需要 h 文件来使用二进制文件和 lib 文件来链接,期望从程序集中运行。
  • @Danny Varod - 具有原型继承的语言(Self、JavaScript)没有类,但它们可能具有反射(JavaScript 允许您遍历对象的成员)。
猜你喜欢
  • 2016-09-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-02
  • 2011-01-23
  • 1970-01-01
  • 2013-08-25
  • 1970-01-01
相关资源
最近更新 更多