多用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 发布!更多文章扫码关注“喵叔呦”

原文地址:https://www.cnblogs.com/gangzhucoll/p/12327574.html

时间: 2024-10-12 15:33:22

多用as少用强制类型转换的相关文章

C++强制类型转换:static_cast、dynamic_cast、const_cast、reinterpret_cast

1. c强制转换与c++强制转换 c语言强制类型转换主要用于基础的数据类型间的转换,语法为: (type-id)expression//转换格式1 type-id(expression)//转换格式2 c++除了能使用c语言的强制类型转换外,还新增了四种强制类型转换:static_cast.dynamic_cast.const_cast.reinterpret_cast,主要运用于继承关系类间的强制转化,语法为: static_cast<new_type> (expression) dynam

el 表达式 强制类型转换

el 表达式 强制类型转换 今天有人问我了这个问题 jsp页面中,能否实现 <%  request.setAttrites("a","1234");  %> a=${(a)+1} 我隐约记得是jsp会默认将a转化为integer类型然后相加的,但是记不太清楚了,于是专门写了这个jsp页面,进行了下验证. 发现确实是这个样子. 然后上网搜索了下,发现el表达式确实是将内容进行相应的值转换后然后返回相应的类型的. 相关帖子: http://www.iteye

第二节 引用变量的强制类型转换

什么是多态 主讲人:王少华       QQ群号:483773664 学习目标: 1)父类与子类间转换:向上转型 2)使用父类作为方法形参实现多态 3)使用父类作为返回值实现多态 一.子类到父类的转换(向上转型) (一)基本数据之间的类型转换 1.自动进行类型转换 //将int型常量或变量的值赋给double型变量,可以自动进行类型转换 int i = 5; double dl = i; 2.强制类型的转换 类型转换运算符是小括号,类型转换运算符的用法是 (type)variable //将do

跟王老师学多态(二): 引用变量的强制类型转换

什么是多态 主讲人:王少华       QQ群号:483773664 学习目标: 1)父类与子类间转换:向上转型 2)使用父类作为方法形参实现多态 3)使用父类作为返回值实现多态 一.子类到父类的转换(向上转型) (一)基本数据之间的类型转换 1.自动进行类型转换 1 2 3 //将int型常量或变量的值赋给double型变量,可以自动进行类型转换 int i = 5; double dl = i; 2.强制类型的转换 类型转换运算符是小括号,类型转换运算符的用法是 (type)variable

c#小灶——自动类型转换和强制类型转换

前面已经认识了不同的数据类型,你们有没有尝试过让不同的数据类型进行运算呢? int a = 1; double b = a; Console.WriteLine(b); 运行结果是:1 我们把一个整型的变量赋值给了一个浮点型的变量,可以正常的输出,如果我们把一个浮点型的变量赋值给一个整型的变量呢? double a = 1; int b = a; Console.WriteLine(b); 这样就会报错. 为什么呢?因为我们之前说过,变量就像一个容器,里面存放着变量的值.而数据类型就相当于容器的

强制类型转换:static_cast、dynamic_cast、const_cast、reinterpret_cast

已剪辑自: https://www.cnblogs.com/chenyangchun/p/6795923.html ? ? 1. c强制转换与c++强制转换 ?c语言强制类型转换主要用于基础的数据类型间的转换,语法为: (type-id)expression//转换格式1 type-id(expression)//转换格式2 ? c++除了能使用c语言的强制类型转换外,还新增了四种强制类型转换:static_cast.dynamic_cast.const_cast.reinterpret_cas

C++强制类型转换操作符 const_cast

const_cast也是一个强制类型转换操作符.<C++ Primer>中是这样描述它的: 1.将转换掉表达式的const性质. 2.只有使用const_cast才能将const性质性质转化掉.试图使用其他三种形式的强制转换都会导致编译时的错误.(添加const还可以用其他转换符,如static_const) 3.除了添加const或删除const特性,使用const_cast符来执行其他任何类型的转换都会引起编译错误.(volatile限定符也包括,不过我不怎么了解,本文主要说const)

C++中的向上类型转换和向下类型转换+四种强制类型转换

转自博客:http://blog.csdn.net/wangweitingaabbcc/article/details/7720979# 在c++的世界中有这样两个概念,向上类型转换,向下类型转换,分别描述的是子类向基类,和基类向子类的强制类型转换. 向上强制类型转换 切割:覆盖方法和子类数据丢失的现象生成切割(slice) class Base { public: int b; virtual void Test() { cout << "base" <<en

java中强制类型转换时,高位数截取成低位数的方法

/** * 强制类型转换中的补码.反码.原码一搞清楚 */ int b=233;//正整数强转 System.out.println((byte)b); //负数:原码的绝对值取反再加一 符号为不变 //00000000 00000000 00000000 11101001 // 1110 1001 补码 // 1110 1000 反码 // 1001 0111 原码 1+2+4+16 =-23 b=-233;//负整数强转 //10000000 00000000 00000000 111010