在.net下面,我们做类型的强制转换有两种方式,比如把对象o转换成A类型的对象:
1。 A a = (A)o;
2。 A a = o as A;
那么这两种方式有什么区别呢?或者说有区分它们的必要么?看了我下面的分析,大家自然就明白了。
实际上,对这个问题不能一概而论,需要考虑这样几种情况。
第一种情况:o是A的子类。
在这种情况下,无论是用方法1还是方法2,效果都是一样的!通过查看上面两种方法的IL代码,会发现它们的IL代码是完全一样的,都是简单的把o出栈,然后保存到a的位置。
因此,当o是A的子类的时候,两种方式没有区别。
现在考虑第二种情况:o不是A的子类。
举个例子,假如o就是object类型吧。
查看两者的IL代码,会发现在第1种方法里面,在把o出栈之后,做了一个castclass操作,它尝试把o转换成A类型。如果成功,当然没的说了。如果失败了,它会丢出一个Invalid cast异常。
在第2种方法里面,在把o出栈之后,做了一个isinst操作,它检测是否可以把o转换成A类型。如果失败了,后面的入栈操作会压入一个null进去,也就是说,你的a变成了null。
好了,现在已经很明了了。可是,区分它们有什么意义呢?
首先,在第一种情况下,我们当然不需要去区分它们了,随便你怎么都可以。因为它们根本就没有区别!
但是在第二种情况下就有区别了。如果用第1种方法,就要考虑处理异常;如果用第2种方法,就必须得在使用a之前做一下非空检测,否则很有可能出现“没有实例化”的异常。但是,实际上,用第1种方法,也要进行非空检测。这是为什么呢?因为假如o是null的话,也是可以成功进行类型转换的。这样看来,无论用那种方法,进行非空检测都是不能省的(当然如果你愿意省掉我也没说的),不过第1种方法还要多个异常处理才算完善。如此看来,使用第1种方法多少费点劲哦。
那么,现在结论出来了——如果可以的话,尽量用as吧!再结合is关键字,在最后给出一个完善的类型转换方案:
A a = o as A;
if (a is A)
...
1。 A a = (A)o;
2。 A a = o as A;
那么这两种方式有什么区别呢?或者说有区分它们的必要么?看了我下面的分析,大家自然就明白了。
实际上,对这个问题不能一概而论,需要考虑这样几种情况。
第一种情况:o是A的子类。
在这种情况下,无论是用方法1还是方法2,效果都是一样的!通过查看上面两种方法的IL代码,会发现它们的IL代码是完全一样的,都是简单的把o出栈,然后保存到a的位置。
因此,当o是A的子类的时候,两种方式没有区别。
现在考虑第二种情况:o不是A的子类。
举个例子,假如o就是object类型吧。
查看两者的IL代码,会发现在第1种方法里面,在把o出栈之后,做了一个castclass操作,它尝试把o转换成A类型。如果成功,当然没的说了。如果失败了,它会丢出一个Invalid cast异常。
在第2种方法里面,在把o出栈之后,做了一个isinst操作,它检测是否可以把o转换成A类型。如果失败了,后面的入栈操作会压入一个null进去,也就是说,你的a变成了null。
好了,现在已经很明了了。可是,区分它们有什么意义呢?
首先,在第一种情况下,我们当然不需要去区分它们了,随便你怎么都可以。因为它们根本就没有区别!
但是在第二种情况下就有区别了。如果用第1种方法,就要考虑处理异常;如果用第2种方法,就必须得在使用a之前做一下非空检测,否则很有可能出现“没有实例化”的异常。但是,实际上,用第1种方法,也要进行非空检测。这是为什么呢?因为假如o是null的话,也是可以成功进行类型转换的。这样看来,无论用那种方法,进行非空检测都是不能省的(当然如果你愿意省掉我也没说的),不过第1种方法还要多个异常处理才算完善。如此看来,使用第1种方法多少费点劲哦。
那么,现在结论出来了——如果可以的话,尽量用as吧!再结合is关键字,在最后给出一个完善的类型转换方案:
A a = o as A;
if (a is A)
...