多用as少用强制类型转换
在 C# 中存在一个名叫静态类型检查的机制,这个机制可以让编译器帮助我们把类型不服的用法找出来,从而使得应用程序在运行期间加少一些类型检查的操作。但是有时候我们还是需要进行运行期类型检查,比如我们在设计框架时将方法的参数类型定义为 object ,那么这时我们就有很大的可能需要将 object 类型的参数先转换为其他类型。我们进行转换时会有两种方法可以使用:一种是强制类型转换,这种方法可以绕过编译器的类型检查,另一种是先通过 is 判断操作是否合理,是否可以转换,然后再使用 as 运算符进行转换,或者使用强制类型转换。下面我们就来讲解一下为什么多使用 as 少使用强制类型转换。
零、as and is
使用 as 进行类型转换会比强制类型转换更加安全,而且运行时效率更高。但是这里有一点需要注意的是 as 和 is 运算符不会考虑用户所定义的类型转换,只有当运行期的类型与要转换到的类型相符时才能顺利进行。一般来说 as 类型转换很少会出现为了类型转换而创建新的对象,只有在 as 运算符把装箱值类型转换未装箱且可以为 null 的类型时才会创建新对象。
is 运算符遵循多态原则,也就是说例如 变量 Husky(哈士奇)是 Dog 类型,并且 Dog 类型继承自 Animal 类型,那么 代码段 husky is Animal
返回值就是 True 。因此我们可以利用这一特性来判断某个对象是否是某个具体类型。当然我们也可用通过 GetType 方法来查询对象的运行期类型,这样可以使开发人员写出比 as 和 is 更加具体更加详细的类型,这主要归功于它所返回的对象类型能够和某种特定类型进行对比。
一、为什么不用强制类型转换
我们先来看一段代码:
try
{
object obj = Factory.GetObject();
Animal animal;
animal = (Animal) obj;
if (animal !=null)
{
// more code
}
// more code
}
catch (InvalidCastExcept ex)
{
// more code
}
在上述代码中我们使用了强制类型转换将 object 类型的变量转换为 Animal 类型,我相信部分开发人员在实际开发中都会这么写,这么些也不为过,但是这其中存在一个问题,开发人员需要处理两个问题。首先程序如果无法将变量 obj 转换为 Animal 类型将抛出 InvalidCastException 异常,因此我们必须捕获,其次在强制类型转换时遇到 null 的时候并不会抛出异常,因此我们还要判断变量 animal 是否为 null 。既然强制类型转换有这个问题,那我们该如何解决呢?这时我们就可以用到 as 和 is 运算符了,同样我们先看一下代码:
try
{
object obj = Factory.GetObject();
if (obj is Animal)
{
Animal animal = obj as Animal;
// more code
}
else
{
// more code
}
}
利用这种方法我们首先判断 obj 是否可以转换为 Animal 类型,如果可以就利用 as 运算符来转换,反之执行其他代码。既不需要捕获错误,也不需要强制转换,减少了代码量同时也减少了代码出错的机率。
as 运算符和强制类型转之间有一个很大的区别,那就是如何对待用户自定义的转换逻辑。 as 和 is 运算符除了必须进行的装箱和拆箱外,它不会执行其他任何操作,也就是说 as 和 is 只会判断带转换对象在运行期是什么类型,并根据结果进行相应的处理。那么如果带转换对象既不属于目标类型也不属于目标类型所派生出来的类型的话, as 操作就宣告失败。强制类型转换则不然,它有可能使用一些类型的转换逻辑进行类型转换,而且不仅仅是用户自定义的转换逻辑,还包含了内置类型之间的转换。但是要注意的是强制类型转换可以会造成信息丢失,例如从 long 强制转换为 short 。
在某些情况下利用强制类型转换从代码上来看似乎可以转换成功,但实际上却转换不成功。这时为什么呢?虽然强制类型转换会把用户自定义的转换逻辑考虑进去,但是它只针对对象的编译期类型,编译期类型并不是是基类型。例如带转换类型在编译期是 object 类型,因此编译器会将它看作 object ,这时如果进行强制类型转换的话就会报错。
前面说了那么多使用 as 的好处,那么在这一小节里我们就来说说在什么时候不能使用 as 和 is 。同样,先来看一小段代码:
object obj =Factory.GetValue();
int num = obj as int;
上面的这段代码运行起来后将会报错,为什么呢?这是因为当 obj 不是 int 类型时返回的值是 null ,但是 int 类型无法接受 null 值。因此当指定类型不可接受 null 值时 as 无法进行类型转换。
二、一个问题
下面我们再思考一个问题,我们都知道 foreach 所针对的序列是非泛型序列它会在迭代过程中自动转换,那么 foreach 的类型转换使用的是 as 呢还是强制类型转换呢?
foreach 使用的时强制类型转换,会把对象从 object 类型转换成循环体所需要的类型,之所以使用强制类型转换是因为 foreach 需要同时应对值类型和引用类型。
三、总结
在开发中我们应该尽量避免使用强制类型转换,强制类型转换在某些情况下可能会出现开发人员预料之外的结果,使用 as 和 is 运算符可以确保对象确实可以进行类型转换时才给出答案,这样可以保证程序的正确性。
本文由博客一文多发平台 OpenWrite 发布!更多文章扫码关注“喵叔呦”
多用as少用强制类型转换的更多相关文章
- C++强制类型转换:static_cast、dynamic_cast、const_cast、reinterpret_cast
1. c强制转换与c++强制转换 c语言强制类型转换主要用于基础的数据类型间的转换,语法为: (type-id)expression//转换格式1 type-id(expression)//转换格式2 ...
- Javascript对象Oject的强制类型转换
众所周知Javascript作为一种动态类型,弱类型的脚本语言其数据类型在很多时候都会发生类型转换.而这些类型转换往往都是隐式的,这让我们在使用Js的时候会产生许多麻烦.而Js的基础数据类型的转换在此 ...
- el 表达式 强制类型转换
el 表达式 强制类型转换 今天有人问我了这个问题 jsp页面中,能否实现 <% request.setAttrites("a","1234"); % ...
- c#小灶——自动类型转换和强制类型转换
前面已经认识了不同的数据类型,你们有没有尝试过让不同的数据类型进行运算呢? ; double b = a; Console.WriteLine(b); 运行结果是:1 我们把一个整型的变量赋值给了一个 ...
- [转载]C++中四种强制类型转换方式
C++中四种强制类型转换方式 原文地址:http://www.cnblogs.com/home123/p/6763967.html 类型转换有c风格的,当然还有c++风格的.c风格的转换的格式很简单( ...
- java中强制类型转换
在Java中强制类型转换分为基本数据类型和引用数据类型两种,这里我们讨论的后者,也就是引用数据类型的强制类型转换. 在Java中由于继承和向上转型,子类可以非常自然地转换成父类,但是父类转换成子类则需 ...
- C++强制类型转换
C语言强制类型转换过于粗暴,任意类型之间都可以进行转换,编译很难判断其正确性; 难于定位,在源码中无法快速定位所有使用强制类型转换的语句. C++将强制类型转换分为4种不同的类型:static_cas ...
- java提高篇(十一)-----强制类型转换
在java中强制类型转换分为基本数据类型和引用数据类型两种,这里我们讨论的后者,也就是引用数据类型的强制类型转换. 在Java中由于继承和向上转型,子类可以非常自然地转换成父类,但是父类转换成子类则需 ...
- JavaScript学习10 JS数据类型、强制类型转换和对象属性
JavaScript学习10 JS数据类型.强制类型转换和对象属性 JavaScript数据类型 JavaScript中有五种原始数据类型:Undefined.Null.Boolean.Number以 ...
随机推荐
- 小白学 Python 爬虫(37):爬虫框架 Scrapy 入门基础(五) Spider Middleware
人生苦短,我用 Python 前文传送门: 小白学 Python 爬虫(1):开篇 小白学 Python 爬虫(2):前置准备(一)基本类库的安装 小白学 Python 爬虫(3):前置准备(二)Li ...
- 原生JavaScript实现评分效果
一.实现原理: 1.要设置一个“大总管变量”,用于记录点击时的星星下标,只声明不赋值. 2.移入每个星星时,先把所有的星星恢复到默认状态:再把当前星星及在它之前的星星设为选中状态. 3.移出每个星星时 ...
- Yolo V3整体思路流程详解!
结合开源项目tensorflow-yolov3(https://link.zhihu.com/?target=https%3A//github.com/YunYang1994/tensorflow-y ...
- 2018南京现场赛K 随机输出
题目链接:http://codeforces.com/gym/101981/attachments n和m太小,空地联通无环,总步数太大,直接随机输出5w个方向 #include<iostrea ...
- eclipse开发工具内打开某js文件总是用记事本方式打开的问题
问题现象: 开发时不知道按到了什么快捷键,导致在某js文件内点击某调用方法时莫名其妙的用记事本方式打开了该js文件,试了几次都是这样.索性将该js文件关掉重新打开,结果双击该文件还是弹出了一个记事本, ...
- NumPy排序
numpy.sort()函数 该函数提供了多种排序功能,支持归并排序,堆排序,快速排序等多种排序算法 使用numpy.sort()方法的格式为: numpy.sort(a,axis,kind,orde ...
- tomcat启动时检测到循环继承而栈溢出的问题:Caused by: java.lang.IllegalStateException: Unable to complete the scan for annotations for web application [/test] due to a StackOverflowError. Possible root causes include
最近在公司更新一个老项目的时候,发现部署项目后tomcat报错,错误如下: Caused by: java.lang.IllegalStateException: Unable to complete ...
- HUAWEI MateBook Fn 功能键/热键切换、设置方法
原文地址:https://club.huawei.com/thread-13130964-1-1.html HUAWE MateBook E/X/D的F1.F2 等键默认是热键优先.在热键模式下,要想 ...
- hge引擎使用技巧
图片周围最好留出一像素,即上下左右都多出一像素.然后使用pngopt.exe处理一下.这样可以减少图片拉伸.旋转时边界模糊的情况 图片宽高最好是 2的N次方
- 代码写不对队-Beta冲刺版本
代码写不对队:Beta冲刺版本 这个作业属于哪个课程 http://edu.cnblogs.com/campus/xnsy/GeographicInformationScience/homework ...