在C#中使用'as'关键字使转换失败时,返回null.背景中发生了什么?它只是简单地抑制异常,所以我不必为失败编写处理代码吗?
我对它的性能特征感兴趣,而不是用try-catch包裹的典型演员.
它使用IL指令isinst
执行转换而不是castclass
转换时使用的指令.这是一个特殊的指令,如果有效则执行转换,否则null
在堆栈上留下.所以不,它不只是抑制异常,并且比这样做快几个数量级.
请注意,isinst
指令之间的行为存在一些差异castclass
- 主要的是isinst
不考虑用户定义的强制转换运算符,它只考虑直接继承层次结构,例如,如果定义以下两个没有继承层次结构的类但是显式转换运算符:
class A { public int Foo; } class B { public int Foo; public static explicit operator B(A a) { return new B { Foo = a.Foo }; } }
然后以下将成功:
var a = new A { Foo = 3 }; var b = (B)a; Console.WriteLine(b.Foo); // prints 3
但是以下不能编译,错误'无法通过引用转换,装箱转换,拆箱转换,换行转换或空类型转换将类型'A'转换为'B'
var a = new A { Foo = 3 }; var b = a as B;
因此,如果您确实设置了任何用户定义的强制转换(由于这个原因和其他原因,对引用类型通常是个坏主意),那么您应该意识到这种差异.
并添加到格雷格的优秀帖子......
第一次在运行时引用一个新的Type时,CLR将一个名为COREINFO_CLASS_STRUCT
(或类似的东西)的结构加载到内存中,该结构包含指向COREINFO_CLASS_STRUCT
该对象派生自的基类的对象的指针...这有效COREINFO_CLASS_STRUCT
为Type的继承链创建一个链接的对象列表,该列表终止于COREINFO_CLASS_STRUCT
for System.Object
.当你执行时isinst
,(或它是类似的方法castclass
)它只需要找到COREINFO_CLASS_STRUCT
你正在检查的对象的具体类型的内存结构,并遍历这个链表以查看你试图转换的Type是否在列表中.
它还包含一个指向单独数组的指针,该数组包含Type实现的所有接口,如果您尝试转换为接口,则必须单独搜索.