一、分类
类型转换分为显示类型转换和隐式类型转换
例如如下例子:
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对象引用所以无法转换