C#用户定义的强制类型转换

一、分类

类型转换分为显示类型转换和隐式类型转换
例如如下例子:
int i=3;
long l=i; //隐式类型转换
short s =(short)I; //显示类型转换
转换过程中可能会导致数据的丢失,例如long类型存储的数据比较大,放到short中可能会有数据丢失。

二、用户自定义强制类型转换
如下代码所示,如果我们想要将结构体成员转换为float怎么计算。.NET本身并没有将结构转换为flaot的方法。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SimpleCurrency
{
    struct Currency
    {
        public uint Dollars;               //两个成员变量
        public ushort Cents;

        public Currency(uint dollars, ushort cents)   //有参构造函数,用作初始化用
        {
            this.Dollars = dollars;   
            this.Cents = cents;
        }

        public override string ToString()   //重写ToString方法
        {
            return string.Format("${0}.{1,-2:00}", Dollars, Cents);
        }

        public static implicit operator float(Currency value) //定义自定义隐式转换为float
        {
            return value.Dollars + (value.Cents / 100.0f);    //转换为float
        }

        public static explicit operator Currency(float value) //定义自定义显示转换为Currency
        {
            uint dollars = (uint)value;                       //先提取整数部分,这里有个前提,float不能为负数
            ushort cents = (ushort)((value - dollars) * 100); //后提取小数部分,然后将小数部分转换为整数并隐式转换为ushort
            return new Currency(dollars, cents);              //
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                Currency balance = new Currency(50, 35);  //新建一个Currency变量并赋值

                //Console.WriteLine(balance);    //输出balance调用,重写的ToString()方法
                //Console.WriteLine("balance is " + balance);  //
                Console.WriteLine("balance is (using ToString()) " + balance.ToString());//

                float balance2 = balance;//隐式转换,将Currency转化为float类型,调用implicit隐式转换

                Console.WriteLine("After converting to float, = " + balance2);

                balance = (Currency)balance2;    //将float类型转化为Currency类型,调用的为explicit
 
                Console.WriteLine("After converting back to Currency, = " + balance);
                Console.WriteLine("Now attempt to convert out of range value of " +
                                  "-$50.50 to a Currency:");
                checked
                {
                    balance = (Currency)(-50.50);   //将Curency类型数据转换为float
                    Console.WriteLine("Result is " + balance.ToString()); //输出的结果是错误的,因为-50.50无法提取出uint的值
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("Exception occurred: " + e.Message);
            }

            Console.ReadLine();
        }

有上述代码可知,重写隐式转换方式需要添加implicit关键字,重写显示转换方法需要加emplicit关键字。在声明的形式上看起来与重写操作符相似。其实却是如此。强制转换本身就是一种另类的操作符。

三、类与类之间的强制转换

首先说明一点,如果两个类之间是继承或间接继承关系的话,及长辈与子辈关系的,两者本身就具有一种强制转换的存在。
例如:
存在两个类:
1、MyDrived //派生类
2、MyBase //基类
其中MyDrived间接或直接继承于MyBase类。
MyDrived derivedObject=new MyDrived();
MyBase baseCopy=derivedObject; //正确,将Mydrived类型对象隐式强制转换为MyBase对象

MyBase derivedObject=new Mydrived(); //正确,将MyDrived类型的对象隐式转换为MyBase对象
MyBase baseObject=new MyBase(); //声明一个MyBase对象
MyDricved derivedCopy1=(MyDerived)drivedObject;
//正确drivedObject虽然是MyBase的对象,但指向的任然是一个完整的MyDrived对象的托管堆空间
MyDrived derivedCopy2=(MyDrived)baseObject;
//错误,baseObject对象指向的就是MyBase对象空间,所以无法赋给MyDrived对象。

若存在一个类MyDrived2也间接的派生MyBase类。它和Mydrived类时平级的情况下,怎么实现类之间的强制转换?
对于这种情况下的强制转换,可以选择放置定义的地方--------在Mydrived类定义内部,或者在Mydrived2的类定义内部。但是不能再其他地方定义。

四、装箱和拆箱数据类型强制转换
例如:
Currency balance=new Currency(40,0);
object baseCopy=balance; //balance是结构变量,它存放在栈中,如果把栈中的数据balance转换为object的对象baseCopy后,会进行装箱操作。
具体操作如下:
编译器会将balance的数据复制一份到托管堆中。放在一个装箱的对象上,然后将装箱的对象的赋值给baseCopy,此时baseCopy中存放的引用就会指向装箱的对象上。此过程反应了装箱操作的步骤

当然有装箱就有拆箱,拆箱操作和装箱的操作时相反的。与基类引用类型和派生引用类型之间的强制转换一样,这是一种显示的强制类型转换,因为如果要强制转换的对象不是正确的类型,就会抛出一个异常。如下:
object drivedObject =new Currency(40,0); //装箱操作
object baseObject=new object(); //
Currency drivedCopy1=(Currency)drivedObject; //拆箱操作
Currency drivedCopy2=(Currency)baseObject; //失败,因为baseObject没有指向drivedObject对象引用所以无法转换

发布了51 篇原创文章 · 获赞 0 · 访问量 878

猜你喜欢

转载自blog.csdn.net/weixin_40786497/article/details/103887810