`
cdragon
  • 浏览: 76970 次
  • 性别: Icon_minigender_1
  • 来自: 北京
最近访客 更多访客>>
社区版块
存档分类
最新评论

effective hierarchy(一)之 基本概念(6)

阅读更多

MSDN,C#2.0

 

转换(conversions)

        转换使一种类型的表达式被视为另外一种类型(的表达式)。转换可以是隐型(自动)、也可以是显型(强制),并因此决定了是否需要显式切换(cast)。如,从int到long的转换是隐式自动的,所以int类型的表达式可以被看作long。反之,从类型long到类型int是显式的,所以要求显式切换。

 

一、隐式转换(七种)

 

 1.标识转换(identity conversion)

    标识转换从任意类型转换为同一个类型。这种转换只存在于诸如(such that),一个实体原本(entity already)拥有到(to)那个类型的必须类型(required type)。所以,该类型被说成是(can be said to)可转换(到那个类型)的(convertible )。

 

 2.隐式数值转换(implicit numeric conversions)

  (1)包括

      a. sbyte  ->short,int,long,float,double,decimal;

      b. byte    ->short,ushort,int,uint,long,ulong,float,double,decimal;

      c. short   ->int,long,float,double,decimal;

      d. ushort ->int,uint,long,ulong,float,double,decimal;

      e. int       ->long,float,double,decimal;

       f. uint     ->long,ulong,float,double,decimal;

      g. long    ->float,double,decimal;

      h. ulong  ->float,double,decimal;

      i.  char    ->ushort,int,uint,long,ulong,float,double,decimal;

      j.  float    ->double

 

  (2)从int,uint,long,ulong到float,以及从long或ulong到double有可能会发生精度丢失,但不会影响到它的数量级;其它的隐式转换从不会丢失信息;

 

  (3)没有到char类型的转换;

 

 3.隐式枚举转换(implicit enumeration convertions)

    允许将十进制整数(decimal-integer-literal)0转成任意枚举类型(enum-type)。

 

 4.隐式引用转换(implicit reference conversions)

  (1)包括下述转换:

       a.任何引用类型->object;

       b.任何类类型(class type)S->任何类类型T,前提是S是T的派生类;

       c.任何类类型S->任何接口类型T,前提是S实现了T;

       d.任何接口类型S->任何接口类型T,前提是S是T的派生接口;

 

       e.数组类型S,元素类型SE->数组类型T,元素类型TE,前提是满足下列条件:

   ~1'S和T的维数相同,元素类型不同;

         ~2'SE和TE是引用的类型,且存在从SE到TE的隐式引用转换。

 

       f.从任何数组类型(array-type)到System.Array;

       g.从任何委托类型(delegate-type)到System.Delegate;

       h.从空类型(null type)到任何引用类型(reference-type)。

 

  (2)隐式引用转换是在引用类型间(between)能被证明(can be proven)总是成功的(always succeed)那些转换,所以也不需要进行运行时检查;

 

  (3)引用转换无论是显式还是隐式,都不会改变被转对象的引用标识(referential identity)。即,虽然引用转换可以改变引用的类型(type of the reference),但它永不改变被指向对象(object being referred to)的类型或值。[注,由上可见,引用的类型与对象是两个概念.]

 

 5.上箱/装箱转换(boxing conversion)

    上箱转换“允许”(permit)数值类型隐型转为引用类型。“上箱”数值类型的值包括分配(allocate)一个对象实例,然后把那个值类型的值拷贝到该实例。

 

 6.隐式常量表达式转换(constant expression)

     包括下列转换:

    (1)只要常量表达式的值是在目标类型范围内,int类型的常量表达式可被转成类型sbyte,byte,short,ushort,uint或ulong;

    (2)只要常量表达式的值不为负,long类型的常量表达式可被转成ulong。

 

 7.用户定义的隐式转换

     由三部分组成:首先是一个可选的(optional)标准隐式转换,紧跟着执行用户定义的隐式转换操作符(operator),最后再跟一个可选的标准隐式转换。

 

 

二、显式转换

 

 1.基本概念

   (1)下列转换归类为显式转换:

             ~所有的隐式转换;

             ~显式的值转换;

             ~显式的枚举转换;

             ~显式的引用转换;

             ~显式的接口转换;

             ~下箱转换;

             ~用户定义的显式转换。

  

   (2)显式转换能够在切换表达式(cast expression)中使用;

 

   (3)显式转换的集合是包括所有的隐式转换在内的,这意味着允许冗余的(reduntant)转换(表达式);

 

   (4)非隐式转换(explicit conversion)的显式转换是这样的转换:

           ~不能够保证总是成功(always succeed);

           ~已知可能丢失信息的;

           ~变换前后的类型显著不同(跨类型域地足够大的差异,across domains of types sufficiently different )以至适于显式表示(merit explicit notation);

 

 2.下列转换属于显式转换:

 

   (1)所有隐式转换;

 

   (2)显式数值转换(numeric conversions)

 

       a.从某个数值类型到另外的不存在(does not already exist)隐式数值转换的数值类型;

 

         1' sbyte     ->byte,ushort,uint,ulong或char;

         2' byte       ->sbyte,char;

         3' short      ->sbyte,byte,ushort,uint,ulong或char;

         4' ushort    ->sbyte,byte,short或char;

         5' int          ->sbyte,byte,short,ushort,uint,ulong或char;

         6' uint        ->sbyte,byte,short,ushort,int或char;

         7' long       ->sbyte,byte,short,ushort,int,uint,ulong或char;

         8' ulong     ->sbyte,byte,short,ushort,int,uint,long或char;

         9' char       ->sbyte,byte或short;

       10' float      ->sbyte,byte,short,ushort,int,uint,long,ulong,char或decimal;

       11' double  ->sbyte,byte,short,ushort,int,uint,long,ulong,char,float或decimal;

       12' decimal ->sbyte,byte,short,ushort,int,uint,long,ulong,char,float或double;

 

       b.因为显式转换包括了所有的隐式和显式数值转换,所以使用切换表达式(cast expression),可以把任意值类型转到任意其它值类型;

 

       c.显式数值转换有可能丢失信息或抛出异常。显式数值转换处理如下:

 

    1' 对于从一个整型到另一个整型的转换,处理是取决于(depend on)在发生转换时的溢出检查(overflow checking)的上下文环境(context):

 

           ·在一个'checked'上下文里,如果源操作数(operand)的值在目标类型的范围内,转换成功;否则抛出System.OverflowException;

 

           ·在一个'unchecked'上下文里,转换始终会成功,处理如下:

               ~如果源类型比目标类型大,那么源值(source value)被截断,方法是放弃(discarding)多出的最高有效位("extra" most significant bits);该结果被视作目标类型的值。

         ~如果源类型比目标类型小,那么源值按符号扩展(sign-extended)或按零扩展(zero-extended),以使它的大小和目标类型相同:如果源类型是有符号的使用符号扩展,无符号的则使用零扩展;该结果被视作目标类型的值。

         ~如果源类型与目标类型大小相同,那么源值被视作目标类型的值;

     

 

         2' 对于从decimal到整型的转换,源值向零舍入到最接近的整数值,并把该整数值作为转换的结果;如果作为结果的整数值不在目标类型的范围内,抛出一个System.OverflowException;

 

 

         3' 对从float或double到整型的转换,它的处理取决于转换发生时溢出检查的上下文:

 

             ·在“checked”上下文里,转换如下处理:

                 ~如果操作数的值是NaN或无限大,则抛出System.OverflowException;

                 ~否则,源操作数向零舍入到最接近的整数。如果整数值在目标类型的范围内,那么值就是转换的结果;

                 ~否则,抛出System.OverflowException.

 

             ·在“unchecked”上下文里,转换始终成功,并且如下处理:

                ~如果操作数的值是NaN或无限大,转换的结果是目标类型未指定的值(unspecified value);

                ~否则,源操作数向零舍入到最接近的整数。如果整数值在目标类型的范围内,那么值就是转换的结果;

                ~否则,转换结果是目标类型的未经指定的值。

 

 

         4' 对从double到float的转换,double值舍入到最接近的float值。如果double值太小以致不能用float值表示,结果变为正零或负零;如果太大以致不能用float值表示,结果变为正无穷大或负无穷大;如果值是NaN,结果仍是NaN。

 

         5' 对从float或double到decimal的转换,源值被转为decimal表示,并且如果需要,在第28位上的小数位被舍入到最接近的数值;如果源值太小以致不能用decimal表示,结果是零;如果源值是NaN,无限大,或太大以致不能表示为decimal,抛出System.OverflowException。

 

         6' 从decimal到float或double的转换,decimal值舍入到最接近的double或float值;因为转换时是有可能发生精度丢失(lose precision),故始终不会出现异常。

 

 

    (3)显式枚举转换,包括,

          ~sbyte,byte,short,ushort,int,uint,long,ulong,char,float,double,decimal<->任意枚举类型;

          ~任何枚举类型<->任何枚举类型;

          ~两个类型间的显式枚举转换,是通过把任何参与的枚举类型当作那个枚举类型的基本类型(underlying)来处理,然后在结果类型之间(between result type)隐式或显式执行数值转换。

            如给定一个基本类型为int的枚举类型E,从E到byte类型被作为从int到byte的显式转换,而从byte到E则是作为从byte到int的隐式数值转换来处理。

 

    (4)显式引用转换

        a. 包括以下转换:

         1'object                       ->任何其他引用类型(reference-type);

         2'类类型(class-type)S->类类型T,前提:S是T的基类;

         3'类类型                      S->接口类型T,前提:S没有密封(sealed)而且S没有实现T;

         4'接口类型                   S->类类型T,前提:T未密封,或T实现了S;

         5'接口类型                   S->任意接口类型T,前提:S不是从T派生出;

 

         6'数组类型S,元素类型SE->数组类型T,元素类型TE,以下条件都为真:

            ~S和T维数相同,只是元素类型不同;

            ~SE、TE是引用类型;

            ~存在从SE到TE的显式引用转换;

            ~从System.Array和它实现的接口到任意数组类型;

            ~从System.Delegate和它实现的接口到任意委托类型;

 

       b.显式引用转换,是在运行时要求检查(require run-time checks)以确保在引用类型之间进行正确转换的那些转换。

 

       c.要使显式引用转换在运行时成功,须满足以下条件:

          ~源操作数的值一定是null;

          ~或源操作数所引用对象的实际类型(actual type)一定是可转换成目标类型的类型(通过隐式引用进行)。

 

        d.显式引用转换失败时,引发System.InvalidCastExpression.

        e.无论是引用转换、隐式转换或显式转换,从不改变被转换对象的引用标识,即,虽然引用转换可以改变引用的类型(type of the reference),但从不改变所引用对象的(object being referred to)类型或值。

 

    (5)显式接口转换;

 

    (6)下箱/拆箱转换(unboxing conversions)

          ~下箱转换“允许”(permit)引用类型显式转换为值类型;

          ~它首先检查对象实例是给定的值类型(given type)装箱了的值(boxed value),然后把值从实例中复制(copy)出来。

 

    (7)用户自定义的显式转换

          ~用户自定义的显式转换包括:一个可选的标准显式转换、紧跟着执行用户自定义的隐式或显式转换操作符、再接可选标准显式转换。

 

三、标准转换(standard conversions)

       标准转换,是作为用户自定义转换的一部分发生的、预定义的(pre-defined)转换。

 

  1.标准隐式转换(特别排除了用户定义的隐式转换)

       ~标识转换 ~隐式数值转换  ~隐式引用转换  ~上箱转换  ~隐式常量表达式转换

 

    2.标准显式转换

       标准显式转换,由所有的标准隐式转换,外加(plus)与标准隐式转换(见1)“逆向的”(opposite)显式转换的子集所组成。换句话说,如果存在一个从 A 类型到 B 类型的标准隐式转换,那么就存在与其对应的两个标准显式转换(从 A 类型到 B 类型,和它的反向转换,即从 B 类型到 A 类型)。

 

四、用户自定义的转换(user-defined conversions,简称udc)

       C# 允许通过用户定义的转换来增加(augment)预定义的(pre-defined)隐式和显式转换。用户自定义的转换,通过在类和结构类型中声明(declare)转换操作符(conversion operator)来引入(introduced)。 

 

  1.允许的用户自定义的转换

    C#只允许声明某些用户自定义的转换(udc)。特别要注意的是,不可能重定义(redefine)一个已经存在的(already existing)隐式或显式转换。从源类型S到目标类型T的转换,只有满足以下全部条件时才可能:

    ~S和T的类型不同;

    ~S和T中有一个是类类型或结构类型,且其中包含操作符的声明(operator declaration);

    ~S和T都不属于object或接口类型;

    ~T和S互不为基类(T不是S的基类,S不是T的基类)。

 

  2.用户自定义转换的测算(evaluation)...略

  3.用户自定义的隐式转换...略

  4.用户自定义的显式转换...略

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics