background image

的类型。在编译器看来,必须是

Functor(Of T, U),两个类型参数都必须是该泛型类定义的。

就在我对此大感抱怨时,我偶然在

C#编译器的源代码(见 Rotor)中看到了它识别运算符

的规则,其中并没有这些限制,只有两条规则

——方法必须是静态的,特定名称的方法;

方法必须带有

specialname 属性。那么我们完全可以骗过编译器,不用它提供的 Operator 关

键字来声明运算符重载过程,而是使用自己编写特定名称的方法,并加以

specialname 的手

法来打造运算符重载过程:

Imports System.Runtime.CompilerServices

Class Functor(Of T, U)
    _
    Public Shared Function op_BitwiseAnd( _
        x As Functor(Of T, Boolean), y As Functor(Of T, Boolean)) _
        As Functor(Of T, Boolean)
    End Function
End Class
System.Runtime.CompilerServices.SpecialNameAttribute 是一个指示编译器为声明成员添

specialname 的特殊属性,C#和 VB 编译器都支持。op_BitwiseAnd 是 VB 和 C#等语言所识

别的与操作运算符过程名称。这样写完以后编译成类库,再以引用

DLL 的方式引用它,你

就会看到编译器将他识别成了我们要的运算符重载过程。当你在

Functor 这样的类型上使用

And 操作时,编译器会告诉你不支持该运算符,仅在 Functor 上才能进行这一操作,编译错
误信息准确无误,真是太棒了。

在我们结束前,我们还可以看看如此手工打造还能突破哪些编译器人为的限制:
可重载

Protected 和 Private 的运算符(尽管这样做几乎没有意义)

可不成对重载比较运算符(

=, >, >=, <=, <, <>)

可以让移位运算符的第二个操作数不是

int(>>和<<样子很好看,但是有了这个限制我

们就不能拿它来干别的事情,现在好了)

可以在

C#中重载仅 VB 支持的运算符,也可以在 VB 中重载仅 C#支持的运算符(当然

要到对方语言中才能生效)

可以让用户自定义显式转换支持泛型类型参数之间更加神奇的写法
用了这种手法,似乎还可以重载诸如

operator+(int, int)之类的运算符,但它们并不能生

效。

.NET 语言编译器中每一项特性,都可能有隐藏在其表面之下的深层次用途。善加研究

后常能发现原来所认识不到的功能。我当然不是在推荐大家乱用运算符重载,只是一种思考,
一种新的灵感。