8.5 转换操作符方法
有时需要将对象从一种类型转换为另一种类型。当源类型和目标类型都是编译器识别的基元类型时,编译器自己就知道如何生成转换对象所需的代码。
如果二者中有不是基元类型的,编译器会生成代码,要求CLR执行转换(强制转型)。这种情况下,CLR只是检查源对象的类型和目标类型是不是相同。
但有时需要将对象从一种类型转换成全然不同的其它类型。假设FCL包含一个Rational有理数类型,那么如果能将Int32或Single转换成Rational会显得很方便,反之亦然。
正确定义转换构造器和方法
为了进行这样的转换,Rational类型应该定义只有一个一个参数的公共构造器,该参数要求是源类型的实例。还应定义无参的公共实例方法ToXxx类似于ToString方法。
以下代码展示了如何为Rational类型正确定义转换构造器和方法。
public sealed class Rational { public Rational(Int32 num){} public Rational(Single num){} public Int32 ToInt32(){} public Single ToSingle(){} }
转换操作符重载
上一节讨论了某些编程语言如何提供操作符重载。事实上,有些编程语言比如C#还提供了转换操作符重载。
转换操作符是将对象从一种类型转换成另一种类型的方法。可以使用特殊的语法来定义转换操作符方法。
CLR规范要求转换操作符重载方法必须是public和static方法。此外,C#要求参数类型和返回类型二者必有其一与定义转换方法的类型相同。
之所以要这样限制,是为了使C#编译器能在一个合理的时间内找到要绑定的操作符方法。
public sealed class Rational { public Rational(Int32 num){} public Rational(Single num){} public Int32 ToInt32(){} public Single ToSingle(){} //由一个Int32隐式构造并返回一个Rational public static implicit operator Rational(Int32 num) { return new Rational(num); } //由一个Single隐式构造并返回一个Rational public static implicit operator Rational(Single num) { return new Rational(num); } //由一个Rational显式返回一个Int32 public static explicit operator Int32(Rational r) { return r.ToInt32(); } //由一个Rational显式返回一个Single public static explicit operator Single(Rational r) { return r.ToSingle(); } }
对于转换操作符方法,编译器即可生成代码来隐式调用转换操作符方法,也可只有在源代码进行了显式转型时才生成代码来调用转换操作符方法。
在C#中,implicit关键字告诉编译器为了生成代码来调用方法,不需要在源代码中进行显式转型。相反,explicit关键字告诉编译器只有在发生了显式转型时才调用方法。
在implicit或explicit之后指定operator关键字告诉编译器该方法是一个转换操作符,在operator之后孩子定对象要转换成什么类型。在圆括号内则指定要从什么类型转换。
使用在Rational定义的转型方法
像前面那样为Rational类型定义了转换操作符后就可以写出向下面这样的C#代码。
public sealed class Program { public static void Main() { Rational r1=5; Rational r2=2.5F; Int32=(Int32)r1; Single s=(Single)r2; } }
在幕后C#编译器检测到代码中的转型,并内部生成IL代码来调用Rational类型定义的转换操作符方法。
编译Rational类型并查看元数据会发现编译器为定义的每个转换操作符都生成了一个方法。