在 C# 中存在一个名叫静态类型检查的机制,这个机制可让编译器帮助咱们把类型不服的用法找出来,从而使得应用程序在运行期间加少一些类型检查的操做。可是有时候咱们仍是须要进行运行期类型检查,好比咱们在设计框架时将方法的参数类型定义为 object ,那么这时咱们就有很大的可能须要将 object 类型的参数先转换为其余类型。咱们进行转换时会有两种方法可使用:一种是强制类型转换,这种方法能够绕过编译器的类型检查,另外一种是先经过 is 判断操做是否合理,是否能够转换,而后再使用 as 运算符进行转换,或者使用强制类型转换。下面咱们就来说解一下为何多使用 as 少使用强制类型转换。安全
使用 as 进行类型转换会比强制类型转换更加安全,并且运行时效率更高。可是这里有一点须要注意的是 as 和 is 运算符不会考虑用户所定义的类型转换,只有当运行期的类型与要转换到的类型相符时才能顺利进行。通常来讲 as 类型转换不多会出现为了类型转换而建立新的对象,只有在 as 运算符把装箱值类型转换未装箱且能够为 null 的类型时才会建立新对象。
is 运算符遵循多态原则,也就是说例如 变量 Husky(哈士奇)是 Dog 类型,而且 Dog 类型继承自 Animal 类型,那么 代码段 husky is Animal
返回值就是 True 。所以咱们能够利用这一特性来判断某个对象是不是某个具体类型。固然咱们也可用经过 GetType 方法来查询对象的运行期类型,这样可使开发人员写出比 as 和 is 更加具体更加详细的类型,这主要归功于它所返回的对象类型可以和某种特定类型进行对比。框架
咱们先来看一段代码:spa
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 。一样,先来看一小段代码:code
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 发布! 更多文章请扫码关注公众号:“喵叔呦”![]()