• Effective C# Item3:操作符as或is优于强制转换


        C#是一种强类型的变成语言,我们一般情况下,不推荐大家对变量的类型进行转换,但是针对代码底层来说,为了对业务代码提供尽可能多的支持,很多时候对方法参数的类型不会做强行限制,而只是将其置为System.Object,那么业务在调用这些方法时,如果希望在方法体内执行用户自定义的方法,就必须对参数的类型进行转换,将System.Object转换为用户自己定义的类型。

        关于类型转换,C#有以下两种方式:1.as或者is;2.强制类型转换。我们推荐使用as或者is。

        as进行类型转换时的机制:它会检查对象的运行时类型,是否是期待类型或者期待类型的派生类型,如果是,就进行转换;如果不是,就返回null。对于null来说,它通过as转换为任何类型后,依然是null,并不会产生异常。as并不会执行用户自定义的类型转换。

        强制类型转换的机制:它使用转换操作符来进行类型转换的工作,在这其中,它会执行.NET框架自带的类型转换机制或者用户自定义的类型转换。这其中,就会有转换成功,但是转换后结果不正确的情况,例如将float强行转换成int,就可能会丢失一些信息。在使用时,需要格外注意这一点。

        下面我们看一段非常有趣的代码,来自《Effective C#》一书。

    代码
    1 public class SecondType
    2 {
    3 private MyType _value;
    4
    5 // other details elided
    6
    7 // Conversion operator.
    8 // This converts a SecondType to
    9 // a MyType, see item 29.
    10   public static implicit operator
    11 MyType( SecondType t )
    12 {
    13 return t._value;
    14 }
    15 }
    16
    17 object o = Factory.GetObject( );
    18
    19 // o is a SecondType:
    20 MyType t = o as MyType; // Fails. o is not MyType
    21
    22 if ( t != null )
    23 {
    24 // work with t, it's a MyType.
    25 } else
    26 {
    27 // report the failure.
    28 }
    29
    30 // Version two:
    31 try {
    32 MyType t1;
    33 t = ( MyType ) o; // Fails. o is not MyType
    34 if ( t1 != null )
    35 {
    36 // work with t1, it's a MyType.
    37 } else
    38 {
    39 // Report a null reference failure.
    40 }
    41 } catch
    42 {
    43 // report the conversion failure.
    44 }
         上述代码中,用户自定义了如何将SecondType转换成MyType,然后通过工厂方法返回一个类型为System.Object的对象,其运行时类型是SecondType,接下来使用as和强制转换两种方式将Object转换成MyType。

        上述两种转换都会是失败的,原因:as和强制转换都是针对变量的运行时类型进行处理的,但是上述代码编译时,是去查看变量的编译时类型,编译器是无法得知变量的运行时类型的,因此,虽然上述代码中使用了强制类型转换,会去查看是否有用户自定义的类型转换,但是编译器只会去查看System.Object和MyObject这两种类型之间是否有用户自定义的类型转换,而不会去查看SecondType和MyType之间是否有用户自定义的类型转换。编译器在编译过程中,能够得到和处理的,始终是变量的编译时类型,同时,用户自定义的类型转换,只作用于对象的编译时类型,而不会作用于对象的运行时类型

        如果希望上述代码转换成功,可以写成以下的方式。

    代码
    1 object o = Factory.GetObject( );
    2
    3 // Version three:
    4 SecondType st = o as SecondType;
    5 try {
    6 MyType t;
    7 t = ( MyType ) st;
    8 if ( t != null )
    9 {
    10 // work with T, it's a MyType.
    11 } else
    12 {
    13 // Report a null reference failure.
    14 }
    15 } catch
    16 {
    17 // report the failure.
    18 }

        以下情况中,是不适合使用as的:

    1. 针对值类型进行类型转换,原因:值类型中不包含null。对于值类型,我们可以先使用is进行类型检查,然后再使用强制类型转换。
    2. foreach语句中的类型转换是强制类型转换,原因:foreach语句的循环变量可能是值类型,也可能是引用类型,因此只能使用强制类型转换。这个也是foreach语句会跑出BadCastException异常的原因。
    3. as进行转换时,会对变量的类型进行检查,当发现变量类型是目标类型或者目标类型的派生类型时,就会进行转换,但是如果我们希望知道变量在运行时详细的类型信息,或者只针对变量是某一特定类型时,才会采取某种操作,这时使用as是不合适的,我们可以使用GetType方法来获取对象的运行时类型的详细信息。  
  • 相关阅读:
    background之你不知道的background-position
    ES6学习笔记(二)
    ES6学习笔记(一)
    将博客搬至CSDN
    Mongodb的性能优化问题
    使用AngularJS实现的前后端分离的数据交互过程
    输出JS代码中的变量内容
    程序生成word与PDF文档的方法(python)
    python 2.7安装某些包出现错误:"libxml/xmlversion.h:没有那个文件或目录"
    Linux中安装配置spark集群
  • 原文地址:https://www.cnblogs.com/wing011203/p/1638212.html
Copyright © 2020-2023  润新知