Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/320.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# “C”;是";接线员-这是反射吗?_C#_.net_Reflection_Introspection_Typing - Fatal编程技术网

C# “C”;是";接线员-这是反射吗?

C# “C”;是";接线员-这是反射吗?,c#,.net,reflection,introspection,typing,C#,.net,Reflection,Introspection,Typing,今天一位同事问了我一个有趣的问题——C#关键字/运算符“是”被认为是反射吗 object tmp = "a string"; if(tmp is String) { } 这个操作符是如何在幕后实现的?它需要反思还是内省?或者由于语言的强类型性质,对象的类型是否可以作为内存中对象的顶级属性立即访问 声明: 请注意,is运算符只考虑引用转换、装箱转换和取消装箱转换。is运算符不考虑其他转换,例如用户定义的转换 考虑装箱和无框转换的能力似乎暗示着我的某种反思。 is操作符基本上决定了强制转换是否可行

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

object tmp = "a string";
if(tmp is String)
{
}
这个操作符是如何在幕后实现的?它需要反思还是内省?或者由于语言的强类型性质,对象的类型是否可以作为内存中对象的顶级属性立即访问

声明:

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


考虑装箱和无框转换的能力似乎暗示着我的某种反思。 is操作符基本上决定了强制转换是否可行,但是当强制转换不可行时,它不会抛出异常,而是返回
false
。如果你考虑投射反射,那么这也是反射。 编辑:


经过一些研究,我发现在
castclass
指令中执行强制转换,而
is
运算符映射到
isinst
指令。FxCop有一个警告,如果您正在执行不必要的强制转换,请先使用
isinst
,然后使用
castclass
指令。即使操作是高效的,它们仍然会有性能成本。

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

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

is
操作符生成
isinst
对象模型IL指令(分区III§4.6),它是基本指令集的一部分,而不是反射库的一部分(分区IV§5.5)

编辑:与反射库相比,
is
操作符效率极高。通过反射,您可以更慢地执行基本相同的测试:

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

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

“is”运算符返回true/false且不为null。我认为您考虑的是“as”运算符。您所描述的是“as”运算符。“is”操作符本质上是相同的操作,只是返回值不同。我在回答中混合了“is”和“as”,你说得对。我已经纠正了我的错误。我没有删掉任何内容,但也许我应该澄清我所说的“昂贵”是什么意思。我对IL效率不太了解,但是FxCop如果您的创建代码既发出ISNST和CAST类指令也会发出警告,因为他们认为它是无效的或“昂贵的”。正如我在第二次编辑中提到的,您应该使用<代码>作为< /代码>,然后使用<代码> null < /Cord>检查引用类型。相反,您使用的是
is
,后面跟着一个cast,这是FxCop提醒您的。值得注意的是,在紧凑的框架上,需要显式检查RTTI的IL(例如
isinst
castclass
)与反射一样慢,而callvirt是高度优化的。寓意:尽量避免在虚拟/抽象方法可以工作的地方使用类型大小写构造。@SamHarwell到ECMA-335的链接断了,你知道更新的版本吗?说反射解析类的成员比解析对象的成员更正确,因为你不需要让实例处于活动状态。同样,反射可以“发现”一个程序集中的哪些类,不仅仅是一个类的成员和其他信息。@ Danny Varod -不是所有的语言都有类或程序集。C++有类和库,java有类和包。面向对象的程序设计定义了对象和类之间的区别。此外,C++不能进行反射——因为二进制文件中没有嵌入所需的信息。这就是为什么您需要h文件来使用二进制文件和lib文件来链接,除了要运行的程序集。@Danny Varod-具有原型继承(Self,JavaScript)的语言没有类,但它们可能有反射(JavaScript允许您遍历对象的成员)。相关的MSDN链接已断开。