C#函數式編程中的緩存技巧詳解。本站提示廣大學習愛好者:(C#函數式編程中的緩存技巧詳解)文章只能為提供參考,不一定能成為您想要的結果。以下是C#函數式編程中的緩存技巧詳解正文
緩存技巧
該節我們將分紅兩部門來說解,第一部門為估計算,第二部門則為緩存。緩存這個技巧對應從事開辟的人員來講長短常熟習的,從頁面緩存到數據庫緩存無處不在,而其最主要的特色就是在第一次查詢後將數據緩存,在今後的查詢進程中就無需從新盤算而直接從內存中將成果前往,年夜年夜進步了機能,而我們這裡的緩存則集中應用在函數上。
估計算
能夠一些人其實不能立馬懂得這個詞的寄義,所以我們就簡略的從生涯例子動身引見一下。許多人在任務中必定會如許干事,好比下級囑咐了你一件事,然則這件事的後半部門要等另外一個同事做好以後把對應的資料給你你能力完成。然則我們弗成能一向比及誰人同事完成了把資料交給我們,我們才去做這件事。而是會將這件事的前半部門做好,那末剩下的只需誰人同事完成並交給我們,我們就直接完成下半部門便可以了。同理如許的思想也能夠用在軟件開辟中,好比上面這個函數:
函數外部是應用a的值盤算出c,最初再將c和b相加得出最初的成果。固然這個例子其實不能完全的表現估計算的特色,但可以或許讓我們懂得估計算是若何完成的。假定這裡的
是一個耗時操作,而且現實應用中會湧現a的值不更改,然則b的值會常常更改的情形,然則每次挪用這個函數都邑從新依據a盤算出c,那末我們就須要必定的方法轉變這個格式,這裡我們可以先測驗考試采取部門運用(這裡引見一個函數式開辟的庫->PortableFCSLib,可以在NuGet中裝置或許到他的github網站高低載:https://github.com/rmoritz/PortableFCSLib):
這裡我們的意圖是只管帳算一次C的值,而不是兩次,然後我們看看終究的輸入成果:
照樣盤算了兩次的C,來由很簡略,由於部門運用僅僅只是應用閉包將參數保留了起來,只要一切參數傳遞完成後才會挪用這個函數,並達不到估計算的後果,所以我們就須要新的方法來完成,上面我們修正DoSomeThing函數:
這裡我們可以看到參數只剩下了a,而前往值則釀成了函數,如許才履行第一次這個辦法以後將管帳算出c值,因為閉包的原因c的值就會被保留。上面我們來看一看若何挪用:
最初看看是否是只盤算了一次C的值:
如許我們就年夜功樂成了,固然筆者在這裡還要再提一下,這些例子僅僅只是為了讀者可以或許疾速的懂得,在現實的應用中還要讀者可以或許依據情形靈巧多變,好比這個函數吸收三個參數,然則前兩個不常常更改,然則第三個卻常常更改,而且函數的外部是依據前兩個參數盤算得出一個成果,而前往值須要依據第三個參數和這個盤算後的值得出,那末我們便可以前往但一個參數的函數,而函數自己須要吸收兩個。
緩存
應用該技巧之前我們須要懂得幾個名詞,就是援用通明和函數純度。這二者都是指在我們挪用一個函數時,不管任什麼時候候,只需傳遞的參數分歧,前往的成果都應當是分歧的。如許的函數我們能力夠應用緩存。起首我們先界說一個函數,而這個函數將會是我們前面須要緩存的函數:
然後我們修正函數使之可以或許停止緩存:
這裡我們可以看到我們應用了字典來對這個函數停止了緩存。函數起首從字典中斷定能否存在參數a的key,假如存在直接前往盤算後的成果,假如不存在則盤算該成果,並保留到字段中,如許我們就完成了一個簡略的緩存。上面我們來看看終究的成果,是否是確切應用了緩存:
當傳遞參數10的時刻,由於緩存中沒有所以停止了緩存,參數5也是一樣,而下一行再次盤算10的時刻就沒有停止盤算而是直接從字典中前往了對應的成果。然則下面這類方法還存在一個成績,假如存在多個函數都須要緩存,則這個類會存在多個字段類型的字段(一些人能夠會問為何不克不及同享一個字典,如許你就要在key的定名上消費必定的工夫,並且很輕易形成反復),那末我們就須要一種可以或許不淨化類的方法來停止緩存,這裡我們先引見若何應用FCSLib中的Memoizer完成外部緩存:
這裡我們可以看到Memoizer地下了一個GetMemory的靜態方法用來獲得對應的緩存對象,然後應用這個前往的對象我們便可以停止緩存,終究的後果跟之前的是一樣的,我們可以看看最初掌握台輸入的成果:
假如你不曉得該為這個函數起甚麼名字,我們可以應用反射來獲得這個函數的全稱,好比上面這個修正以後的DoSomeThing函數就是應用了這個方法:
固然除手動修正函數的方法,我們也能夠采取主動化來使沒有益用緩存的函數應用緩存技巧,上面我們來寫一個函數來完成這個功效:
我們可以看到白色框住的部門,其實就是應用了閉包,在這個函數之上又嵌套了一層函數,如許我們就可以夠停止緩存了,只要在緩存中不存在時才挪用函數求值,然則面臨多個參數的情形,下面這些沒法正常緩存了。那末我們就須要應用深度緩存,而所謂的深度緩存就是應用字典套字典來停止保留的,好比上面這個函數,須要傳遞兩個參數,那末對應的緩存就是:
然後就是Main中停止挪用:
最初我們可以看到上面的這個成果,第一次挪用sfunc(10,5)時樹立了緩存,再第二次傳遞異樣的參數挪用後可以看到掌握台並沒有輸入對應的字符串:
固然如許字典的嵌套在參數許多的情形下,會顯得很龐雜,而且也會消費許多內存。然則以後也沒有異常好的處理計劃,上面我們還可以應用之前寫的Cache函數來完成下面這類多個參數的緩存:
重點是我們白色框住的那部門,詳細的嵌套就是第一個字典的key是第一個參數,value就是下個函數的援用,固然這個函數是經由Cache包裝以後的,那末天然在挪用value的函數以後天然也起到了緩存感化。