在类型转换过程中,有些类型之间可以直接转换(如int->double),而有些就必须显示强制转换(如double->int),类型转换遵循这样的规则:
无论源变量中存什么值,转换成目标变量总是安全的(不会丢失数据,不会异常等等),那么就可以直接转换(隐式转换)。反之,如果转换成目标变量可能会出错,那么久必须显示的强制转换。
1. 用户定义的数据类型转换:
用户定义类型转换的语法如下:
public static explicit operator T1(T2 value); public static implicit operator T1(T2 value);
T1是目标类型,T2是源类型。explicit和implicit表示是要显示转换还是隐式转换。因为类型转换和实例无关,所以我们必须定义为public static。
示例1:
1 using System; 2 3 namespace ConsoleApplication22 4 { 5 class Program 6 { 7 static void Main(string[] args) 8 { 9 try 10 { 11 Currency balance = new Currency(50, 35); 12 Console.WriteLine(balance); 13 Console.WriteLine("balance is " + balance); 14 Console.WriteLine("balance is (using ToString()) " + balance.ToString()); 15 16 float balance2 = balance; 17 Console.WriteLine("After converting to float, = " + balance2); 18 balance = (Currency)balance2; 19 Console.WriteLine("After converting back to Currency, = " + balance); 20 21 balance = (Currency)(-50.5); 22 Console.WriteLine("Result is " + balance.ToString()); 23 } 24 catch (Exception e) 25 { 26 Console.WriteLine("Exception occurred: " + e.Message); 27 } 28 29 Console.ReadLine(); 30 } 31 } 32 33 struct Currency 34 { 35 public uint Dollars; 36 public ushort Cents; 37 38 public Currency(uint dollars, ushort cents) 39 { 40 this.Dollars = dollars; 41 this.Cents = cents; 42 } 43 44 public override string ToString() 45 { 46 return string.Format("${0}.{1,-2:00}", Dollars, Cents); 47 } 48 49 public static implicit operator float(Currency value) 50 { 51 return value.Dollars + (value.Cents / 100.0f); 52 } 53 54 public static explicit operator Currency(float value) 55 { 56 checked 57 { 58 uint dollars = (uint)value; 59 ushort cents = Convert.ToUInt16((value - dollars) * 100); 60 return new Currency(dollars, cents); 61 } 62 } 63 } 64 }
输出:
注:示例1中显示转换cents时没有直接使用代码:ushort cents = (ushort)((value-dollars)*100); 是为了避免圆整错误
示例2:
1 using System; 2 3 namespace ConsoleApplication23 4 { 5 class Program 6 { 7 static void Main(string[] args) 8 { 9 Cube cube = new Cube(2, 5, 6); 10 double volume = cube; 11 Console.WriteLine("volume: {0}", volume); 12 13 volume = 27; 14 cube = (Cube)volume; 15 Console.WriteLine(cube.ToString()); 16 17 Console.ReadLine(); 18 } 19 } 20 21 public struct Cube 22 { 23 double Length; 24 double Width; 25 double Height; 26 public Cube(double length, double width, double height) 27 { 28 this.Length = length; 29 this.Width = width; 30 this.Height = height; 31 } 32 33 public double GetVolume() 34 { 35 return Length * Width * Height; 36 } 37 38 public override string ToString() 39 { 40 return String.Format("Lenght: {0} Width: {1} Height: {2}", Length, Width, Height); 41 } 42 43 public static implicit operator double(Cube cube) 44 { 45 return cube.GetVolume(); 46 } 47 48 public static explicit operator Cube(double d) 49 { 50 Cube b = new Cube(); 51 b.Length = b.Width = b.Height = Math.Pow(d, 1 / 3d); 52 return b; 53 } 54 } 55 }
输出:
2. 类之间的数据类型转换
定义不同结构或类之间的数据类型转换时允许的,但是有两个限制:
- 如果某个类直接或间接继承了另一个类,就不能定义这两个类之间的数据类型转换(这些类型的类型转换已经存在)
- 数据类型转换必须在源或目标数据类型的内部定义。
3. 基类和派生类之间的数据类型转换
- 源和目标的数据类型都是引用类型
考虑两个类MyBase和MyDerived,其中MyDerived直接或间接派生于MyBase。
首先,从MyDerived到 MyBase的转换(派生类转换为基类):
MyDerived derivedObject = new MyDerived();
MyBase baseCopy = derivedObject;
1 namespace ConsoleApplication24 2 { 3 class Program 4 { 5 static void Main(string[] args) 6 { 7 MyBase derivedObject = new MyDerived(); 8 MyBase baseObject = new MyBase(); 9 10 MyDerived derivedCopy1 = (MyDerived)derivedObject; // ok 11 MyDerived derivedCopy2 = (MyDerived)baseObject; // Throw exception:Unable to cast object of type 'ConsoleApplication24.MyBase' to type 'ConsoleApplication24.MyDerived' 12 } 13 } 14 15 public class MyDerived : MyBase 16 { } 17 18 public class MyBase 19 { 20 } 21 }