天天躁日日躁狠狠躁AV麻豆-天天躁人人躁人人躁狂躁-天天澡夜夜澡人人澡-天天影视香色欲综合网-国产成人女人在线视频观看-国产成人女人视频在线观看

手工打造運(yùn)算符重載過程

除了J#外,所有微軟支持的.NET開發(fā)語言現(xiàn)在均支持運(yùn)算符重載,因此純粹為C#簡化寫法一樣特性現(xiàn)已成為一種.NET開發(fā)中值得研究的一項(xiàng)重要語言特性。有人認(rèn)為運(yùn)算符重載其實(shí)就是簡化寫法,滿足模擬基本類型操作的小功能,沒有必要深究。但我覺得要多思考一層,為什么我們總希望模擬基本類型的操作?因?yàn)檫\(yùn)算符重載能夠?qū)⒉僮髦芯Y化,能夠自動(dòng)推測(cè)靜態(tài)過程的主體。

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

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

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

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

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

Type.op_Operator(x, y) '靜態(tài)方法
x op y '運(yùn)算符寫法

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

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

很遺憾,這樣會(huì)編譯錯(cuò)誤。作為運(yùn)算符重載過程,其參數(shù)至少有一個(gè)必須是定義運(yùn)算符的類型。在編譯器看來,必須是Functor(Of T, U),兩個(gè)類型參數(shù)都必須是該泛型類定義的。就在我對(duì)此大感抱怨時(shí),我偶然在C#編譯器的源代碼(見Rotor)中看到了它識(shí)別運(yùn)算符的規(guī)則,其中并沒有這些限制,只有兩條規(guī)則——方法必須是靜態(tài)的,特定名稱的方法;方法必須帶有specialname屬性。那么我們完全可以騙過編譯器,不用它提供的Operator關(guān)鍵字來聲明運(yùn)算符重載過程,而是使用自己編寫特定名稱的方法,并加以specialname的手法來打造運(yùn)算符重載過程:

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是一個(gè)指示編譯器為聲明成員添加specialname的特殊屬性,C#和VB編譯器都支持。op_BitwiseAnd是VB和C#等語言所識(shí)別的與操作運(yùn)算符過程名稱。這樣寫完以后編譯成類庫,再以引用DLL的方式引用它,你就會(huì)看到編譯器將他識(shí)別成了我們要的運(yùn)算符重載過程。當(dāng)你在Functor這樣的類型上使用And操作時(shí),編譯器會(huì)告訴你不支持該運(yùn)算符,僅在Functor上才能進(jìn)行這一操作,編譯錯(cuò)誤信息準(zhǔn)確無誤,真是太棒了。

在我們結(jié)束前,我們還可以看看如此手工打造還能突破哪些編譯器人為的限制:

可重載Protected和Private的運(yùn)算符(盡管這樣做幾乎沒有意義)
可不成對(duì)重載比較運(yùn)算符(=, >, >=, <=, <, <>)
可以讓移位運(yùn)算符的第二個(gè)操作數(shù)不是int(>>和<<樣子很好看,但是有了這個(gè)限制我們就不能拿它來干別的事情,現(xiàn)在好了)
可以在C#中重載僅VB支持的運(yùn)算符,也可以在VB中重載僅C#支持的運(yùn)算符(當(dāng)然要到對(duì)方語言中才能生效)
可以讓用戶自定義顯式轉(zhuǎn)換支持泛型類型參數(shù)之間更加神奇的寫法
用了這種手法,似乎還可以重載諸如operator+(int, int)之類的運(yùn)算符,但它們并不能生效。

.NET語言編譯器中每一項(xiàng)特性,都可能有隱藏在其表面之下的深層次用途。善加研究后常能發(fā)現(xiàn)原來所認(rèn)識(shí)不到的功能。我當(dāng)然不是在推薦大家亂用運(yùn)算符重載,只是一種思考,一種新的靈感。

NET技術(shù)手工打造運(yùn)算符重載過程,轉(zhuǎn)載需保留來源!

鄭重聲明:本文版權(quán)歸原作者所有,轉(zhuǎn)載文章僅為傳播更多信息之目的,如作者信息標(biāo)記有誤,請(qǐng)第一時(shí)間聯(lián)系我們修改或刪除,多謝。

主站蜘蛛池模板: 久久久久久久久久毛片精品美女 | 久久精品亚洲精品国产欧美 | 精品少妇爆AV无码专区 | 亚洲成色WWW久久网站夜月 | 国产亚洲日韩另类在线观看 | 99久久国产露脸精品国产吴梦梦 | 日韩中文字幕欧美在线视频 | 啦啦啦WWW在线观看免费高清版 | 国产久久re6免费热在线 | 亚洲AV成人无码网天堂 | 性春院| 美女伊人网 | 久久精品99国产精品日本 | japansemature护士 JAPANRCEP老熟妇乱子伦视频 | chinesevideoshd性舞| 亚洲国产综合久久久无码色伦 | 中文字幕视频在线免费观看 | 天美传媒麻豆精品 | 国产成人亚洲精品无广告 | 99久久香蕉 | 99久视频只有精品2019 | 善良的小峓子2在钱中文版女主角 | 影音先锋色av男人资源网 | a视频在线免费观看 | 亚洲第一色网 | 美女被爽cao免费漫画 | 国产精品亚洲视频在线观看 | 亚洲综合中文字幕无线码 | 老师别揉我胸啊嗯小说 | 国产成人在线小视频 | 伦理片92伦理午夜 | 免费三级现频在线观看 | 亚洲色综合狠狠综合区 | 新影音先锋男人色资源网 | 久久婷婷国产五月综合色啪最新 | 果冻传媒2021精品影视 | 国产精品久久久久久人妻香蕉 | 做暖暖视频在线看片免费 | 首页 国产 亚洲 中文字幕 | 免费成人高清在线视频 | 国内精品伊人久久久久 |