一区二区久久-一区二区三区www-一区二区三区久久-一区二区三区久久精品-麻豆国产一区二区在线观看-麻豆国产视频

手工打造運算符重載過程

除了J#外,所有微軟支持的.NET開發語言現在均支持運算符重載,因此純粹為C#簡化寫法一樣特性現已成為一種.NET開發中值得研究的一項重要語言特性。有人認為運算符重載其實就是簡化寫法,滿足模擬基本類型操作的小功能,沒有必要深究。但我覺得要多思考一層,為什么我們總希望模擬基本類型的操作?因為運算符重載能夠將操作中綴化,能夠自動推測靜態過程的主體。

首先是操作中綴化。函數調用其實是一種前綴操作,函數(代表操作)總是在參數(代表操作數)之前寫出。這樣執行序列操作時運行的順序其實和書寫的順序相反:

H(x,y)
G(H(x, y), z)
F(G(H(x, y), z), w)

序列運行的順序是H->G->F但是卻要反過來寫,二元參數距離函數名越來越遠。我們按照計算機執行的順序思考,卻要反過來寫,多少有些不爽。成員函數擴展方法的寫法則是將操作數(對象)寫在前面:

x.H(y)
x.H(y).G(z)
x.H(y).G(z).F(w)

這樣就將書寫的順序正過來了。這是一個甚好的方案,但是在不具備擴展方法的今天,有些事情是成員函數做不了的。比如在我的VBF里,我希望Functor可以進行And, Or等邏輯運算,而Functor之間只能進行算術運算,Functor之間只能進行連接運算,而且規則還不一樣……但是成員函數沒有根據類型參數選取不同重載的能力,也就是說.NET泛型無法進行特化操作。在.NET中具有編譯期類型判定的機制只有兩個:函數根據參數類型的重載和用戶自定義隱式轉換(相當于根據返回類型重載)。我們可以用Functor<,>類型的靜態方法來實現根據類型參數不同的不同重載。但是靜態方法不但要寫全類型的名字,還是前綴操作,使用起來讓人甚為不爽,這時就會發現,運算符重載是我們夢寐以求的東西。

Type.op_Operator(x, y) '靜態方法
x op y '運算符寫法

以上兩種是等價的,可以看到運算符重載不僅可以通過x,y的類型推測靜態方法的調用主體Type,還可以將操作轉化為中綴寫法——比后綴更適合表現二元運算。既然這么完美,我們能不能這樣寫呢?

Class Functor(Of T, U)
    Public Shared Operator And( _
        x As Functor(Of T, Boolean), y As Functor(Of T, Boolean)) _
        As Functor(Of T, Boolean)
    End Operator
End Class

很遺憾,這樣會編譯錯誤。作為運算符重載過程,其參數至少有一個必須是定義運算符的類型。在編譯器看來,必須是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語言編譯器中每一項特性,都可能有隱藏在其表面之下的深層次用途。善加研究后常能發現原來所認識不到的功能。我當然不是在推薦大家亂用運算符重載,只是一種思考,一種新的靈感。

NET技術手工打造運算符重載過程,轉載需保留來源!

鄭重聲明:本文版權歸原作者所有,轉載文章僅為傳播更多信息之目的,如作者信息標記有誤,請第一時間聯系我們修改或刪除,多謝。

主站蜘蛛池模板: 一区二区三区视频在线 | 97狠狠操 | 精品亚洲成a人在线观看 | 精品福利一区二区免费视频 | 五月婷中文字幕 | 一本一本久久a久久综合精品蜜桃 | 日韩欧美一区黑人vs日本人 | 上色天天综合网 | 在线一区二区三区 | 超碰97人人射妻 | 日本韩国欧美在线 | 免费黄色美女网站 | 九九视频九九 | 一区二区三区中文字幕 | 黄色小视频免费 | 91麻豆精品激情在线观看最新 | 九九99在线视频 | 一级做a爰片性色毛片刺激 一级做a爰片性色毛片黄书 | 人人爰人人人人人鲁 | 午夜男人剧场 | 国产精亚洲视频 | 看全色黄大色黄大片女图片 | 亚洲成人91| 日本在线观看永久免费网站 | 亚洲综合激情视频 | 怡红院美国十次成人影院 | 黑人专区| 亚洲大片免费观看 | 国产综合一区二区 | 欧美中文字幕一区二区三区 | 国产在线观看精品一区二区三区91 | 中文字幕在线观看一区二区三区 | 免费在线精品视频 | 精品一区二区三区的国产在线观看 | 国产中文字幕视频 | 五月婷婷丁香在线观看 | 国产精品一区二区免费 | 黄色小视频在线免费看 | 久久久网站亚洲第一 | 国产精彩对白综合视频 | 精品欧美一区二区精品久久 |