自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

擴(kuò)展方法延伸的編程思維

開(kāi)發(fā)
在本文中,筆者主要是從擴(kuò)展方法說(shuō)起,談到我們?cè)撛趺礃痈玫木帉?xiě)更貼近自然語(yǔ)言的程序,然后再到一些沒(méi)有擴(kuò)展方法語(yǔ)言給出的折衷實(shí)現(xiàn),延伸出一種新的編程思維。不足之處,還望大家指正!

  擴(kuò)展方法延伸的編程思維:

  1. Helper大爆炸

  .NET Framework為我們提供了豐富的類(lèi)庫(kù),但是這并不是***地,在大部分的時(shí)間,我們都需要為我們的項(xiàng)目特殊定制我們的通用類(lèi)庫(kù)。

  常常,我們都可以構(gòu)造一個(gè)類(lèi),類(lèi)里封裝一些方法。但是對(duì)于很多時(shí)候,我們并沒(méi)有辦法提取出這樣一個(gè)類(lèi),舉一個(gè)小例子,我們?cè)诤芏鄷r(shí)候,需要把url給保存到數(shù)據(jù)庫(kù)里,作為一個(gè)唯一標(biāo)識(shí),但是我們知道url所占空間很大,如果用url來(lái)建立索引的話是非常耗費(fèi)空間,而且影響效率的,那么我們最常用的辦法就是把url做一個(gè)Hash來(lái)作為索引的替代品。

  這個(gè)時(shí)候,我們根本就沒(méi)有辦法說(shuō)我們來(lái)怎么樣提取一個(gè)類(lèi),然后在類(lèi)里寫(xiě)這樣一個(gè)方法,這個(gè)時(shí)候,我們通常就只能這樣:

  1. public static class HashHelper   
  2. {   
  3.     public static string GetHashCode(string s)   
  4.     {   
  5.         //GetHashCode........   
  6.         return String.Empty   
  7.     }   

  然后我們會(huì)這樣使用:

  1. public static void Main(string[] args)   
  2. {   
  3.     string url = "www.fandongxi.com"   
  4.     string sql = "insert into Test values('"+HashHelper.GetHashCode(url)+"')"   
  5.     //執(zhí)行SQL   

  這里,只是一個(gè)例子,并不是說(shuō)我們要這個(gè)樣子拼接字符串。

  很快,肯定又會(huì)出現(xiàn)一個(gè)情況,說(shuō),我們要保存網(wǎng)頁(yè)的內(nèi)容,但是網(wǎng)頁(yè)的內(nèi)容直接存儲(chǔ)到數(shù)據(jù)庫(kù)里太大了,那么我們就需要對(duì)網(wǎng)頁(yè)文本做一個(gè)Base64的編碼然后壓縮。//之前這里些的是錯(cuò)的,被很多人挑了錯(cuò)誤。

  那么,我們就又得繼續(xù)寫(xiě):

  1. public static class Base64Helper   
  2. {   
  3.     public static string GetBase64Text(string text)   
  4.     {   
  5.         //Base64........   
  6.         return String.Empty   
  7.     }   

  接下來(lái)我們?cè)谑褂玫牡胤骄陀侄喑鰜?lái)一個(gè)Base64Helper。那么過(guò)幾天,還會(huì)出現(xiàn)SHA1Helper , MD5Helper等等各種各樣的Helper。

  漸漸地,我們會(huì)不會(huì)發(fā)現(xiàn),Helper的數(shù)量已經(jīng)讓我們難以忍受了呢?

#p#

  2. 擴(kuò)展方法的提出

  接下來(lái)的事情,我們都知道了,在.NET Framework 3.5中,也就是在C#3.0中,引入了擴(kuò)展方法這個(gè)概念。

  那就讓我們擴(kuò)展方法來(lái)解決上面的難題。

  各位現(xiàn)在一定知道,無(wú)論是做UrlHashCode,還是Base64壓縮,還是SHA1加密,還是MD5加密,這些都是針對(duì)字符串,或者說(shuō)是一段文本的處理,那么很自然地,我們就需要把這些全部寫(xiě)入String類(lèi)的擴(kuò)展方法中。

  1. public static class ExtensionClass   
  2. {   
  3.     public static string GetHashCode(this string s)   
  4.     {   
  5.         //........   
  6.     }   
  7.     public static string GetBase64Text(this string text)   
  8.     {   
  9.         //.......   
  10.     }   
  11. }  
  12.  
  13. public static void Main(string[] args)   
  14. {   
  15.     string url = "www.fandongxi.com"   
  16.     string sql = "insert into Test values('"+url.GetHashCode()+"')"   
  17.         //執(zhí)行SQL   

  在這里,我不想剖析去讀擴(kuò)展方法的實(shí)現(xiàn)本質(zhì),這里我們只談編程思維和擴(kuò)展方法所帶來(lái)的意義。

  3. 擴(kuò)展方法讓C#更加面向?qū)ο?/STRONG>

  從面向?qū)ο蟮慕嵌葋?lái)看,世間萬(wàn)物皆為對(duì)象,所有屬性,所有方法都是屬于某一個(gè)對(duì)象的,那么再?gòu)倪@個(gè)角度看開(kāi)去,本就不應(yīng)該存在靜態(tài)類(lèi),也不應(yīng)該存在靜態(tài)方法,所謂的靜態(tài),不過(guò)是面向?qū)ο笳Z(yǔ)言對(duì)并不成熟的語(yǔ)法實(shí)現(xiàn)的一種屈從罷了

  我們要求Base64加密后的文本,其實(shí)是文本調(diào)用自身的一個(gè)方法,之所以我們?cè)谥暗姆椒ㄖ行枰粋€(gè)Base64Helper,而不能這樣子直接調(diào)用,只是因?yàn)?NET Framework無(wú)法預(yù)計(jì)到我們所有的業(yè)務(wù)場(chǎng)景,所以把只能把最通用的方法封裝到已有的類(lèi)庫(kù)中。

  4. 從擴(kuò)展方法向外談一些

  讓我們從擴(kuò)展方法逐漸地向外圍來(lái)探討一些關(guān)于編碼規(guī)范,以及一些代碼優(yōu)雅的問(wèn)題。我們先不妨假設(shè)我們并不存在“+”運(yùn)算符,或者說(shuō),我們禁止在程序中使用+運(yùn)算符,那么也就是說(shuō),我們需要對(duì)“+”這個(gè)操作來(lái)做一個(gè)簡(jiǎn)單的封裝,那么我們常規(guī)意義上會(huì)怎么做?

  1. public int Add(int a,int b)   
  2. {   
  3.     return a+b;   
  4. }  
  5.  
  6. public static void Main(string[] args)   
  7. {   
  8.     int result = Add(3,4)   
  9.     Console.WriteLine(result)   

  讓我們來(lái)看這個(gè)函數(shù),我們順著代碼的意思向下讀,加,3,4。這明顯是不符合我們常規(guī)的數(shù)學(xué)思維的,如果用了擴(kuò)展方法之后,我們一定是應(yīng)該這樣來(lái)寫(xiě)。

  1. public static class Extension   
  2. {   
  3.     public static int Add(this int a,int b)   
  4.     {   
  5.         return a+b;   
  6.     }   
  7. }  
  8.  
  9. public static void Main(string[] args)   
  10. {   
  11.     int a = 3;   
  12.     a.Add(b)   

  可是這個(gè)"."運(yùn)算符看上去還是那么有點(diǎn)別扭…..沒(méi)辦法,至少這樣讀上去讓我們的代碼順暢了很多不是么?像寫(xiě)文章,說(shuō)話一樣寫(xiě)代碼一直是我們程序員追求的***境界,就像這樣的代碼總是好的。

  Good:people.eat(food)

  而不是Bad:Eat(people,food)

  對(duì)把!

#p#

  5. 前綴,中綴和后綴表達(dá)式

  說(shuō)到這,就不得不談?wù)勄熬Y,中綴和后綴表達(dá)式了。

  學(xué)過(guò)數(shù)據(jù)結(jié)構(gòu)的朋友們,一定都記得在數(shù)據(jù)結(jié)構(gòu)中,有一道經(jīng)典的習(xí)題,就是利用“棧”來(lái)實(shí)現(xiàn)前綴,中綴和后綴表達(dá)式的轉(zhuǎn)換。在考試題中也經(jīng)常會(huì)出現(xiàn)這樣的習(xí)題。那現(xiàn)在讓我們來(lái)復(fù)習(xí)一下,什么是前綴,中綴和后綴表達(dá)式。

  前綴表達(dá)式就是不含括號(hào)的算術(shù)表達(dá)式,而且它是將運(yùn)算符寫(xiě)在前面,操作數(shù)寫(xiě)在后面的表達(dá)式,也稱為“波蘭式”。

  大名鼎鼎的Lisp就是前綴表達(dá)式的典型,讓我們看一個(gè)最簡(jiǎn)單的小例子,還是那個(gè)經(jīng)典的斐波那契數(shù)列:

  1. (define (fib n)   
  2.     (fib-iter 1 0 n))  
  3.  
  4. (defile (fib-iter a b count)   
  5.     (if (= count 0)   
  6.         b   
  7.         (fib-iter (+ a b) a (- count 1))))  

  每次寫(xiě)Lisp的時(shí)候,都會(huì)被密密麻麻的括號(hào)所嚇到,可是真的沒(méi)什么太好的解決方案呢!

  中綴表達(dá)式就很簡(jiǎn)單了,和我們常規(guī)所涉及到的代碼是一樣的,后綴也是一個(gè)道理,在此就不再一一贅述。鑒于后綴的應(yīng)用不是很大,在此我們也只談?wù)勄熬Y和中綴的意義。

  那么我們想想,為什么Lisp要采用這么蹩腳的前綴表達(dá)式語(yǔ)法呢?

  記得在大二***次學(xué)習(xí)C語(yǔ)言的時(shí)候,老師讓我們寫(xiě)一個(gè)簡(jiǎn)單的計(jì)算器,當(dāng)時(shí)每個(gè)同學(xué)都寫(xiě)出了+,-,*,/的操作,但是在當(dāng)時(shí)大多數(shù)的我們都沒(méi)有辦法寫(xiě)出更為常用的混合運(yùn)算,以及()的操作,當(dāng)時(shí)只有班上某鶴立雞群的哥們寫(xiě)出了讓我們當(dāng)時(shí)完全無(wú)法看懂的代碼。再直到大三學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu),再反過(guò)來(lái)想他當(dāng)時(shí)的代碼,才恍然大悟。

  廢話說(shuō)了一堆,那么其實(shí)前綴表達(dá)式***的意義就是他更貼近計(jì)算機(jī)的思維,他只需要兩種操作就能完成運(yùn)算,就是入棧和出棧。讓我們來(lái)看一個(gè)簡(jiǎn)單的小例子

  3+(1-4),首先這是一個(gè)中綴表達(dá)式,把他轉(zhuǎn)換為前綴表達(dá)式就是+3 – 1 4,計(jì)算機(jī)會(huì)從右向左來(lái)掃描這個(gè)表達(dá)式,4入棧,1入棧,然后遇到 - ,1和4出棧,并且完成運(yùn)算,(-3)入棧,3進(jìn)棧,+入棧,(-3)和3出棧,完成運(yùn)算。

  也就是說(shuō),其實(shí)在計(jì)算機(jī)完成我們所編寫(xiě)的數(shù)學(xué)操作時(shí),其實(shí)往往都是把我們的中綴表達(dá)式首先轉(zhuǎn)換為前綴表達(dá)式,然后完成計(jì)算,而Lisp采用前綴表達(dá)式,則是省去了這一個(gè)步驟,從而提高解釋器的效率。

  那我們就來(lái)總結(jié)下前綴和中綴表達(dá)式的意義。

  前綴表達(dá)式更加貼近計(jì)算機(jī)思維,方便計(jì)算。而中綴表達(dá)式更加貼近數(shù)學(xué)思維,容易被我們所理解。

  那回顧下,我們之前寫(xiě)Add的代碼,如果說(shuō)我們?nèi)サ?運(yùn)算符,而且方法不加括號(hào),是否采用擴(kuò)展方法,把C#的語(yǔ)法和Lisp的語(yǔ)法相結(jié)合,其實(shí)就成了這樣的形式。

  1. public int Add(int a,int b)   
  2. {   
  3.     return a+b;   
  4. }  
  5.  
  6. public static void Main(string[] args)   
  7. {   
  8.     (set! result (Add a b))   
  9. }  
  10.  
  11. public static class Extension   
  12. {   
  13.     public static int Add(this int a,int b)   
  14.     {   
  15.         return a+b;   
  16.     }   
  17. }  
  18.  
  19. public static void Main(string[] args)   
  20. {   
  21.     (set! result (a Add b))   

  還是后者更貼近我們的自然思維一些。

  .NET Framework很強(qiáng)大,給我們提供了擴(kuò)展方法這個(gè)概念,那么如果沒(méi)有了擴(kuò)展方法,其他語(yǔ)言給出了怎么樣的解決方案呢?

  那讓我們來(lái)看看Haskell給出的方案。

#p#

  5. 看看Haskell的方法

  Haskell是一門(mén)函數(shù)式的語(yǔ)言,在FP大行其道的今天,Haskell這門(mén)久居深宮的語(yǔ)言也漸漸地浮出了水面。

  廢話不多說(shuō),我們只來(lái)看看Haskell是如何在沒(méi)有擴(kuò)展方法的情況下來(lái)解決語(yǔ)法和自然思維不相協(xié)調(diào)的問(wèn)題的。

  讓我們先來(lái)編寫(xiě)一個(gè)簡(jiǎn)單的Haskell函數(shù)。

  add x y = x + y

  代碼很簡(jiǎn)單,沒(méi)什么值得多說(shuō),讓我們來(lái)看看Haskell怎么調(diào)用。

傳統(tǒng)調(diào)用

 

  這是我們傳統(tǒng)的調(diào)用方式,可是Haskell為了更貼近我們的自然思維,為參數(shù)個(gè)數(shù)數(shù)量為2的方法提供了這樣一個(gè)便捷的調(diào)用:

便捷調(diào)用

 

  這就是Haskell為我們提供的“中綴表達(dá)式”的解決方案。

  擴(kuò)展方法很好,但是當(dāng)我們的語(yǔ)言中沒(méi)有擴(kuò)展方法的時(shí)候,Haskell給我們提供了一個(gè)優(yōu)秀的典范。

  6. 語(yǔ)言和類(lèi)庫(kù)

  說(shuō)到這,我就想順便談?wù)勱P(guān)于語(yǔ)言擴(kuò)展和類(lèi)庫(kù)擴(kuò)展的問(wèn)題。

  在《Masterminds of Programmming》一書(shū)中,Python語(yǔ)言之父Guido在接受采訪時(shí),談到PEP(Python增強(qiáng)處理)時(shí),順便說(shuō)到了關(guān)于在編寫(xiě)編程語(yǔ)言時(shí),如何來(lái)根據(jù)用戶的意見(jiàn)來(lái)處理語(yǔ)言實(shí)現(xiàn)的問(wèn)題。

  他談到:

  如果某個(gè)用戶提出一個(gè)新特性,它幾乎不會(huì)成功。因?yàn)橛脩魧?duì)實(shí)現(xiàn)沒(méi)有全面的理解,他幾乎不可能提出一個(gè)合理的新特性。

  那么在我看來(lái)什么是用戶?用戶就是使用這門(mén)語(yǔ)言來(lái)完成工作任務(wù)的人,他們往往需要的都是增加一個(gè)新功能,換句話說(shuō),他們需要的僅僅是一個(gè)方法而已。

  那么什么是增加語(yǔ)言特性,什么是增加類(lèi)庫(kù)方法,Guido也給出了比較合理的解釋。

  如果某個(gè)特性對(duì)于Web來(lái)說(shuō)確實(shí)很棒,那么,對(duì)于加到語(yǔ)言中來(lái)說(shuō),就未必是優(yōu)秀的特性了。如果它確實(shí)利于編寫(xiě)更短的函數(shù),或者是有利于編寫(xiě)可維護(hù)更強(qiáng)的類(lèi),把它添加到語(yǔ)言中可能就是一件好事。

  其實(shí)Guido的意思很簡(jiǎn)單,是否增加到語(yǔ)言中,關(guān)于在于這個(gè)特性是否是領(lǐng)域相關(guān)的,如果是領(lǐng)域相關(guān)的,也許它需要做的僅僅是擴(kuò)展類(lèi)庫(kù),無(wú)論是增加Python的類(lèi)庫(kù),還是用C去擴(kuò)展Python API,總之無(wú)需對(duì)語(yǔ)言做出改變。

  那么對(duì)于C#來(lái)說(shuō),什么是類(lèi)庫(kù)的修改,什么是語(yǔ)言的修改,在我看來(lái),每一個(gè)版本的修改都一定有著類(lèi)庫(kù)的修改,但是如果說(shuō)到語(yǔ)言的修改,應(yīng)該是僅僅當(dāng)MSIL發(fā)生變動(dòng)的時(shí)候,我們才可以說(shuō)語(yǔ)言發(fā)生了修改。//仔細(xì)想了一下,這個(gè)觀點(diǎn)有問(wèn)題....但是我沒(méi)找到更合適的語(yǔ)言來(lái)做比喻。也許應(yīng)該說(shuō),只有當(dāng)語(yǔ)法的編譯規(guī)則發(fā)生改變的時(shí)候,我們才可以說(shuō)語(yǔ)言發(fā)生了修改。

  Python也是一樣,增加了方法充其量是類(lèi)庫(kù)的修改,而僅僅是語(yǔ)言的解釋過(guò)程都發(fā)生了修改才可以算得上是語(yǔ)言層面的修改,例如從Python 2.x到Python3.x的大版本變動(dòng)。

  總結(jié)

  在本文中,主要是從擴(kuò)展方法說(shuō)起,談到我們?cè)撛趺礃痈玫木帉?xiě)更貼近自然語(yǔ)言的程序。

  然后再到一些沒(méi)有擴(kuò)展方法語(yǔ)言給出的折衷實(shí)現(xiàn)。而對(duì)于Python,C等其他語(yǔ)言,我尚且沒(méi)有找到合適的方法來(lái)解決問(wèn)題。如果各位有好的辦法,希望各位補(bǔ)充給出解決方法。

【編輯推薦】

  1. 擴(kuò)展方法(1)
  2. 3.1 擴(kuò)展方法及其使用規(guī)則
  3. .NET Framework擴(kuò)展方法基本常識(shí)簡(jiǎn)介
  4. 4.1 擴(kuò)展方法概述
  5. 淺析C#擴(kuò)展方法
責(zé)任編輯:韓亞珊 來(lái)源: 天極網(wǎng)
相關(guān)推薦

2011-04-19 09:51:27

PythonNautilus

2011-07-21 17:19:47

java面向?qū)ο?/a>

2009-06-22 13:48:00

Java編程思想面向?qū)ο?/a>

2017-05-31 14:43:57

2015-04-07 09:10:00

2015-04-16 09:41:01

2018-08-22 10:27:35

編程人工智能機(jī)器人

2009-08-27 18:04:01

c#擴(kuò)展方法string

2022-02-25 15:49:13

大數(shù)據(jù)十四五應(yīng)用

2009-06-19 18:49:07

ibmdwLotus

2009-08-31 14:45:10

C#擴(kuò)展方法

2012-11-21 10:08:50

2012-09-17 11:24:40

IBMdw

2019-01-16 18:39:24

數(shù)據(jù)開(kāi)發(fā)模型

2009-09-11 10:20:36

Linq擴(kuò)展方法

2009-09-17 11:29:50

Linq擴(kuò)展方法

2009-09-10 16:32:19

LINQ Where

2009-08-10 17:36:17

C#擴(kuò)展方法

2021-07-14 10:39:28

JqueryVue 編程

2015-11-05 08:59:19

編程Visual Stud擴(kuò)展
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)