跟小静读CLR via C#(08)操作符

跟小静读CLR via C#(08)-操作符

对于操作符,我们并不陌生,例如+,-,*,%等二元操作符,以及++,!等一元操作符。但是对于非基元类型,我们需要通过一些自定义方法才能使用这些操作符。今天主要和大家分享关于操作符重载和转换操作符的知识。


一、操作符重载方法

CLR并不知道操作符,操作符重载对于它来说只是一些方法而已。但是CLR规定了语言应该如何公开操作符重载,每种编程语言自行决定是否支持操作符重载。

定义操作符重载方法注意两点:

  • CLR规范要求操作符重载方法必须是 public static 类型。
  • C#要求操作符重载方法必须有一个参数的类型和当前定义这个方法的类型相同。否则会产生编译错误

         image

操作符重载实例

我们为非基元类型Complex重载操作符 “+”.

image

定义之后,可以使非基元类型Complex方便的进行+操作。

image

image

Sepecialname标记

ILDaxm.exe查看Complex类的元数据,发现产生了一个op_Addition项。如果重载其他操作符,也会自动产生相应的specialname标记。

image

在编译过程中,当代码中出现“+”操作符时,编译器会自动检查op_Addition的specialname标记,并且检测参数类型兼容性。

下面两个表是C#允许重载的一元操作符和二元操作符。简单了解一下就好,没必要强记。

image

   image

二、转换操作符方法

当两个非基元类型的实例需要相互转换时,我们需要定义转换操作符方法。转换操作符是指将对象从一个类型转换成另一个类型的方法。

两大规定

  • CLR要求转换操作符重载方法必须是public static 方法。
  • C#要求参数类型和返回类型必须至少有一个与定义转换方法的类型相同。

另外,为了完成转换操作,我们应该在类型内定义两类方法:

  • 实例公共构造器。参数是源类型的实例
  • 无参公共实例方法Toxxx。该方法将定义类型的实例转换成xxx类型。

转换操作符例子

为Rational(有理数)类型定义转换操作符,方便与Int32类型实例进行相互转换。

image

implicit和explicit

在这个例子中,我们定义了两种转换操作符方法:implicit关键字表示在源代码中不需要进行显式转型;explicit关键字表示进行显式转型时才调用该方法。Operator关键字表明该方法是一个转型操作符。

使用ILDasm.exe查看,

image

可以发现添加了两个方法:op_Explicit和op_Implicit。只有当转换后不丢失精度的前提下,才能进行隐式转换;如果会发生精度丢失,则只能定义为显式转换。

定义完成之后我们就可以方便的进行转型调用了。

static void Main(string[] args)
        {
            Rational r1 = 5;            // 隐式转换
            Int32 x = (Int32)r1;       // 显示转换
        }

关于重载

在上面的例子中,实际上一个类型经常会和多个类型实例进行转换操作,此时就需要再定义其他转换操作符,例如public static explicit operator Single(Rational r),也就是进行方法重载。对于重载,我们并不陌生,特殊之处在于这两个explicit重载方法仅仅通过返回值类型不同来区分的。

CLR允许定义多个同名方法,只要每个方法的参数或者返回值类型有所区别即可。但是在C#判断方法的唯一性时,除了方法名称外只考虑参数的区别,而忽略掉方法的返回类型。所以,上面的两个重载方法仅有返回类型的差异实际上是C#放宽限制的特例。

原文地址:https://www.cnblogs.com/janes/p/2125394.html