zoukankan      html  css  js  c++  java
  • C#中的转换

    11.3  转换

    到目前为止,在需要把一种类型转换为另一种类型时,使用的都是类型转换。而这并不是唯一的方式。

    在计算过程中,int可以采用相同的方式隐式转换为long或double,还可以定义所创建的类(隐式或显式)转换为其他类的方式。

    为此,可以重载转换运算符,其方式与本章前面重载其他运算符的方式相同。

    11.3.1  重载换算运算符

    除了重载如上所述的数学运算符之外,还可以定义类型之间的隐式和显式转换。

    如果要在不相关的类型之间转换,这是必须的,例如,如果在类型之间没有继承关系,也没有共享接口,这是必须的。

    下面定义ConvClass1和ConvClass2之间的隐式转换,即编写下述代码:

    ConvClass1 op1 = new ConvClass1();
    ConvClass2 op2 = op1;

    另外,还可以定义一个显式转换,在下面的代码中调用

     ConvClass1 op3 = new ConvClass1();
     ConvClass2 op4 = (ConvClass2)op3;

    例如,考虑下面的代码

    public class ConvClass1
        {
            public int val;
            public static implicit operator ConvClass2(ConvClass1 op1)//隐式转换
            {
                ConvClass2 retrunVal = new ConvClass2();
                retrunVal.val = op1.val;
                return retrunVal;
            }
        }
    
        public class ConvClass2
        {
            public double val;
            public static explicit operator ConvClass1(ConvClass2 op2)//显式转换
            {
                ConvClass1 returnVal = new ConvClass1();
                returnVal.val = (int)op2.val;
                return returnVal;
            }
        }

    其中,ConvClass1包含一个int值,ConvClass2包含一个double值。

    int值可以隐式转换为double值,所以可以在ConvClass1和ConvClass2之间定义一个隐式转换。

    但是反过来就不行了,应把ConvClass2和ConvClass1之间的转换定义为显式转换。

    在代码中,用关键字implicit和explicit来指定这些转换,如上所示。对于这些类,下面的代码就很好:

                try
                {
                    ConvClass1 op1 = new ConvClass1();
                    op1.val = 3;
                    ConvClass2 op2 = op1;
                    Console.WriteLine(string.Format("op2.val = {0}", op2.val));
    
                    ConvClass2 op3 = new ConvClass2();
                    op3.val = 3e15;
                    ConvClass1 op4 = (ConvClass1)op3;
                    Console.WriteLine(string.Format("op4.val = {0}", op4.val));
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }

    在第二个转换中,没有做数据转换的合法性检查,数据会丢失。

    本来是3e15但是转换的时候,数据溢出了。超出了int的范围。

    解决防范:可以使用checked关键字,进行检查:

     public class ConvClass2
        {
            public double val;
            public static explicit operator ConvClass1(ConvClass2 op2)
            {
                ConvClass1 returnVal = new ConvClass1();
                checked { returnVal.val = (int)op2.val; }
                return returnVal;
            }
        }

    如果在显示转换中使用了checked关键字,之前的转换就会产生异常。

    13.2    as 运算符

    as运算符使用下面的语法,把一种类型转换为指定的引用类型

    <operand> as <type>

    这只适用于下列情况:

    <operand>的类型是<type>类型

    <operand>可以隐式转换为<type>类型

    <operand>可以封箱到<type>类型中

    如果不能从<operand>转换为<type>,则表达式的结果就是null。

    注意,基类到派生类的转换可以使用显示转换来进行,但这并不总是有效的。考虑前面示例中的两个类ClassA和ClassD。其中ClassD派生于ClassA:

     interface IMyInterface
        { }
        class ClassA : IMyInterface
        { }
        class ClassD : ClassA
        { }

    以下的代码使用as运算符把obj1中存储的ClassA实例转换为ClassD实例:

    ClassA obj1 = new ClassA();
    ClassD obj2 = obj1 as ClassD;

    则obj2的结果为null

    还可以使用多态性把ClassD实例存储在ClassA类型的变量中。下面的代码演示了这个方面,ClassA类型的变量包含ClassD类型的实例,使用as运算符把ClassA类型的变量转换为ClassD类型。

    ClassD obj1 = new ClassD();
    ClassA obj2 = obj1;
    ClassD obj3 = obj2 as ClassD;

    其中obj3包含与obj1相同的对象引用,而不是null。

    因此,as运算符非常有用,因为下面使用简单类型转换的代码会抛出一个异常:

    ClassA obj1 = new ClassA();
    ClassD obj2 = (ClassD)obj1;

    而as表达式只会把null赋予obj2,不会抛出异常。这表示,下面的代码在C#应用程序中是很常见的

    (使用本章前面开发的2个类:Animal和派生于Animal的一个类Cow)

            public void MilkCow(Animal myAnimal)
            {
                Cow myCow = myAnimal as Cow;
                if (myCow != null)
                {
                    myCow.Milk();
                }
                else
                {
                    Console.WriteLine("{0} isn't a cow,and so can't be milked.", myAnimal.Name);
                }
            }

    这要比检查异常要简单得多!

  • 相关阅读:
    仿苹果原生头部动画
    cookie VS sessionstorge VS localstorge
    require实现单页应用程序(SPA)
    物体position:absolute后设置left:50%发生的有趣小事
    C/JS_实现选择排序
    C/JS_实现冒泡排序
    C_求质数
    C/JS_二分法查找
    JS_高程6.面向对象的程序设计(2)创建对象_3 构造函数存在的问题
    CSS_常见布局
  • 原文地址:https://www.cnblogs.com/chucklu/p/4418256.html
Copyright © 2011-2022 走看看