从IL看强制转换和is,as
来源:互联网 发布:ipad版淘宝怎么开店 编辑:程序博客网 时间:2024/05/21 18:50
1.强制类型转换。
注意:下面的所有的IL代码都是release版,并且优化之后的。
Is和as的作用不多说,下面主要从IL角度来看一下他们的工作原理。
请看如下代码:
class CastTest { static void Main(string[]args) { objecto = "OK!"; stringstr = (string)o; Console.WriteLine(str); }}
然后使用ILDASM查看他的IL代码,如下:
首先,使用ldstr指令将对象“OK“的引用加载到栈上,然后使用stloc.0指令将引用赋值给变了o。因此,ldstr “OK” 和stloc.0相当于object o=”OK“。
注:stloc.0指令的全写为:“store the value on the top of stack to thefirst local. “意思将栈顶元素存储到第一个局部变量中。IL栈分为三个部分:参数区,局部变量区,计算栈。可以将他们分别看成一个数组,要访问他们都需要通过下标索引,譬如想要将第一个局部变量加载到计算栈上,就可以使用ldloc.0指令,其中0就是索引0.如果想要将计算栈顶元素存储到局部变量区中的第0个局部变量就可以使用stloc.0指令。
接下来,ldloc.0指令将变量o加载到计算栈中,然后使用castclass指令将o强制转换为System.String。
这里的核心指令是castclass,需要注意这个指令在转换不成功的时候,会抛出一个InvalidCastException异常。因此,在高级语言中一般建议不使用强制类型转换,而是使用可替代的is或者as关键字。
2.Is和as
由于使用强制转换可能会在运行的时候抛出一个异常,所以作为替代,C#提供了另一种类型转换方式,使用这种转换方式,即使在转换不成功的时候,也不会抛出一个异常,这就是使用关键字is和as来实现的。
修改上述代码如下:
class CastTest { static void Main(string[]args) { objecto = "OK!"; stringstr = o as string; Console.WriteLine(str); } }
编译后,查看他的IL代码,如下:
这一次,C#没有生成castclass指令,而是生成了一个isinst指令。这个指令弹出栈顶元素,然后将其准换为System.String类型,如果转换成功那么就将转换后的类型压入栈顶,如果转换失败,那么就将一个null入栈,而不是抛出一个异常。
因此,我们只需要检查结果是否为null,就可以知道转换是否成功。
事实上,编译器为不仅仅为as关键字生成了isinst指令,也为is关键字生成了isinst。将上述代码修改如下:
class CastTest { static void Main(string[]args) { objecto = "OK!"; if(o is string) { //然后可以使用你想要的方式进行转换 } } }
IL代码如下:
由于is关键字需要一个判断,所以编译器不仅仅会生成一个isinst指令,紧接着还会使用brfalse.s指令来判断转换的结果是否为flase(flase和null都是一个0),如果转换失败就跳转到IL_001b处,否则继续执行下面的指令。
正如你所看到的,编译器会为as关键字生成一个isinst指令,为is关键字生成两个指令:isinst和brfalse。但是,我们一般不会在源代码直接使用as关键字,而是在as之后,在来一个if语句来判断换转是否成功。如下:
class CastTest { static void Main(string[]args) { objecto = "OK!"; stringstr = o as string; if(str != null) { Console.WriteLine(str); } } }
查看一下IL代码,会发现什么呢?正如你所想的那样,这时候as和is的效果是一样。那么为什么还要推荐使用as而不是is呢?看一下二者的使用方式便知:
class CastTest { static void Main(string[]args) { objecto = "OK!"; stringstr = o as string; if(str != null) { Console.WriteLine(str); } } }
上面代码只转换一次(string str=o as string)。
再看下面代码:
class CastTest { static void Main(string[]args) { objecto = "OK!"; if(o is string) { stringstr = (string)o; } } }
这里却需转换两次,一处在o is string,这里主要使用isinst指令;一处在(string)o,这里使用castclass指令。
- 从IL看强制转换和is,as
- 3、强制类型转换、as和is
- C#的as, is和类型强制转换
- C#中is和as、向上强制转换和向下强制装换之详解
- 读书笔记之C#的is和as操作符强制类型转换
- 读书笔记之C#的is和as操作符强制类型转换收藏
- 黑马程序员--.Net学习日记——C#强制转换as is 的用法和区别
- [C#] as 和 is 运算符以及安全的类型强制转换
- [C#] as 和 is 运算符以及安全的类型强制转换
- as和is类型转换
- as和()强制类型转换的区别
- as和强制类型转换的区别
- as 和 强制转换的区别
- 条款3:操作符is或as优于强制转换
- C#下的强制类型转换应用分析:()、is、as
- C#中的AS、IS运算符与强制类型转换
- as3强制转换 as
- 建议3: 区别对待强制转型与as和is
- Python学习笔记(十):Python文档
- ARM中断
- 用工厂方法代替new操作.
- Python中函数个数可变参数的传递
- 全排列
- 从IL看强制转换和is,as
- 检查nginx配置,重载配置以及重启的方法
- 配置 Mysql 允许远程连接
- Adaboost+Haar分类器(二)
- 动态规划DP持续分析(update)
- hdu_1754 I Hate It
- uva146 ID Codes
- Google C++ Mocking Framework for Dummies 翻译
- 男人八题系列