8.4 操作符重载方法
有的语言允许类型定义操作符应该如何操作类型到实例。例如,许多类型比如System.String都重载了相等==和不等!=操作符。
CLR对操作符重载一无所知,他甚至不知道什么是操作符。是编程语言定义了每个操作符的含义,以及这些特殊符号出现时应该生成什么样的代码。
例如在C#中,向基元类型到数字应用+符号,编译器生成将两个数加到一起到代码。将+符号应用于String对象,编译器生成将两个字符串连接到一起的代码。
测试不等性时,C#使用!=符号,而VB使用<>。最后,^在C#中的含义是异或XOR,在VB中为求幂。
虽然CLR对操作符一无所知,但她确实规定了语言应该如何公开操作符重载,以便由另一种语言的代码使用。每种编程语言自己决定是否支持操作符重载。
C#对操作符重载的要求
编译源代码时,编译器会生成一个标识操作符行为的方法。CLR规范要求操作符重载方法必须是public和static方法。
另外C#要求操作符重载方法至少有一个参数的类型与当前定义这个方法的类型相同。之所以这样限制,是为了时C#编译器能在合理时间内找到要绑定的操作符方法。
定义一个操作符重载方法
以下C#代码展示了在一个类中定义的操作符重载方法:
public sealed class Complex { public static Comple operator+(Complex c1,Complex c2){} }
编译器为名为op_Addition的方法生成元数据方法定义项。这个方法定义项还设置了specialname标志,表明这是一个特殊方法。
编译器看到源代码中出现一个+操作符会检查是否有一个操作数到类型定义了名为op_Addition的specialname方法,而且该方法的参数兼容于操作数的类型。
如果存在这样的方法,编译器就生成调用它的代码。不存在就报告编译错误。
C#到一元操作符及其相容于CLS(公共语言规范)的方法名
C#操作符 | 特殊方法名 | 推荐的相容于CLS的方法名 |
+ | op_UnaryPlus | Plus |
- | op_UnaryNegation | Negate |
! | op_LogicalNot | Not |
~ | op_OneComplement | OnesComplement |
++ | op_Increment | Increment |
-- | op_Decrement | Decrement |
无 | op_True | IsTrue{get;} |
无 | op_False | IsFalse{get;} |
更多参见CLR via C#第187页表8-2
CLR规范规定了许多额外的可重载的操作符,但C#不支持这些额外的操作符。
检查Framework类库FCL的核心数值类型,会发现他们没有定义任何操作符重载方法。之所以不定义是因为编译器会在代码中专门查找针对这些基元类型执行的操作,并声称直接操作这些类型的实例的IL指令。
如果类型要提供方法,而且编译器要生存代码来调用这些方法,方法调用就会产生额外的运行时开销。
另外方法最终都要执行一些IL指令来完成你希望的操作。这正是核心FLC类型没有定义任何操作符重载方法的原因。