zoukankan      html  css  js  c++  java
  • 改善C#程序的157个建议(连载3)

    建议3:区别对待强制转型与as和is

      在阐述本建议之前,首先需要明确什么是强制转型,以及强制转型意味着什么。从语法结构上来看,类似下面的代码就是强制转型。

    secondType = (SecondType)firstType;

      但是,强制转型可能意味着两件不同的事情:

      1)FirstType和SecondType彼此依靠转换操作符来完成两个类型之间的转型。

      2)FirstType是SecondType的基类。

      类型之间如果存在强制转型,那么它们之间的关系,要么是第一种,要么是第二种,不能同时既是继承的关系,又提供了转型符。

      首先看第一种情况,当FirstType和SecondType存在转换操作符时的代码如下:

    1. class FirstType  
    2. {  
    3.     public string Name { get; set; }  
    4. }  
    5. class SecondType  
    6. {  
    7.     public string Name { get; set; }  
    8.     public static explicit operator SecondType(FirstType firstType)  
    9.     {  
    10.         SecondType secondType = new SecondType() { Name = "转型自:" + firstType.Name };  
    11.         return secondType;  
    12.     }  
    13. }

      在这种情况下,如果想转型成功则必须使用强制转型,而不是使用as操作符。

    1. FirstType firstType = new FirstType() { Name = "First Type" };  
    2. SecondType secondType = (SecondType)firstType;         //转型成功  
    3. //secondType = firstType as SecondType;     //编译  
    4.                             //期转型失败,编译通不过

      不过,这里需要讨论的不是像以上代码这样的简单应用,而是稍微复杂一点的应用。为了满足更进一步的需求,我们需要写一个通用的方法,需要对FirstType或者SecondType做一些处理,方法看起来应该像下面这样:

    1. static void DoWithSomeType(object obj)  
    2. {  
    3.     SecondType secondType = (SecondType)obj;  
    4. }

      注意:是否对这种方法声明方式有一点熟悉?事实上,如果再加一个参数EventArgs,上面的方法就可以注册成为一个典型的CLR事件方法了。

      如果运行本段代码,会带来一个问题:若在调用方法的时候,传入的参数是一个FirstType对象,那就会引发异常。你可能会问,在上一段代码中,有这样的写法:

    1. FirstType firstType = new FirstType() { Name = "First Type" };  
    2. SecondType secondType = (SecondType)firstType;

      而DoWithSomeType方法提供的代码,看起来无非像下面这样:

    1. FirstType firstType = new FirstType() { Name = "First Type" };  
    2. object obj = firstType;  
    3. SecondType secondType = (SecondType) obj;

      也就是说,这段代码与上段代码相比,仅仅多了一层转型,实际上obj还是firstType,为什么转型就失败了呢?这是因为编译器还不够聪明,或者说我们欺骗了编译器。针对(SecondType) obj,编译器首先判断的是:SecondType和object之间有没有继承关系。因为在C#中,所有的类型都是继承自object的,所以上面的代码编译起来肯定没有问题。但是编译器会自动产生代码来检查obj在运行时是不是SecondType,这样就绕过了转换操作符,所以会转换失败。因此,这里的建议是:

      如果类型之间都上溯到了某个共同的基类,那么根据此基类进行的转型(即基类转型为子类本身)应该使用as。子类与子类之间的转型,则应该提供转换操作符,以便进行强制转型。

      注意:再次强调,转型操作符实际上就是一个方法,类型的转换需要手工写代码完成。

  • 相关阅读:
    Python随笔之字典Dict
    Python随笔之列表List
    Python基础整理,懒得分类了,大家对付看看吧
    shell批量推送公钥脚本
    Xcode 切换target 之后打包失败
    百度导航sdk错误日志
    前端项目中去掉替换双引号
    taro3.x项目中引用taro-ui以及taro-iconfont-cli
    taro
    JS中some() every() forEach() map() filter()的区别
  • 原文地址:https://www.cnblogs.com/xyqCreator/p/2626498.html
Copyright © 2011-2022 走看看