c# yield提高代碼性能和可讀性
對于”yield”這個關(guān)鍵字我已經(jīng)見過N次了,直到最近我才知道這個關(guān)鍵字所蘊(yùn)含的力量。我將在下面展示出一些使用”yield”讓你的代碼有更高可讀性和更好性能的例子
為了讓你對yield有一些快速概覽,我首先要展示一個沒有使用這個關(guān)鍵字的例子,下面的代碼很簡單
IList<string> FindBobs(IEnumerable<string> names)
{
var bobs = new List<string>();
foreach(var currName in names)
{
if(currName == "Bob")
bobs.Add(currName);
}
return bobs;
}
注意在這里我使用IEnumerable<string>作為參數(shù)類型并以IList<string>作為返回類型,通常來說,我更傾向于在參數(shù)輸入的類型方面的范圍越寬越好,但在返回類型上面更加嚴(yán)格(譯者按:即輸入時多用基類或接口,返回時用子類或?qū)崿F(xiàn)類),對于輸入來說,如果你需要用foreach來對其進(jìn)行循環(huán)的話,使用IEnumerable會更有意義。而對于輸出(譯者按:也就是返回),我使用接口來讓實現(xiàn)部分可以改變。在這里我想讓調(diào)用者省去生成列表的麻煩,所以我選擇list作為返回類型.
而問題在于,我的設(shè)計并不具有可鏈接性,這樣的設(shè)計需要產(chǎn)生列表作為返回值,實現(xiàn)上,這個列表或許不會很大,但這并不必要
現(xiàn)在,讓我們來看看以“yield”的方式來做這些,而后我會解釋如何使用它,以及它工作的原理。
IEnumerable<string> FindBobs(IEnumerable<string> names)
{
foreach(var currName in names)
{
if(currName == "Bob")
yield return currName;
}
}
在這個版本中,我們將返回類型改為IEnumerable,并且我們使用”yield return”.注意我再也不需要創(chuàng)建一個列表,現(xiàn)在是不是有些迷惑的?別著急,在理解它的工作方式的情況它會變的越來越簡單.
當(dāng)使用”yield return”關(guān)鍵詞組時,.net會為你生成一大串管道代碼,你可以盡管假裝這是個魔法。當(dāng)開始在被調(diào)用的代碼中循環(huán)時(這里不是list),實現(xiàn)上發(fā)生的是這個函數(shù)被一遍一遍的調(diào)用,但每一次都從上一次執(zhí)行退出的部分開始繼續(xù)執(zhí)行
傳統(tǒng)的執(zhí)行方法
調(diào)用函數(shù)
函數(shù)執(zhí)行并返回list
調(diào)用部分使用返回的list
Yield的執(zhí)行方法
調(diào)用函數(shù)
調(diào)用者請求item
下一個item返回
回到步驟2
雖然yield執(zhí)行的實現(xiàn)貌似有些復(fù)雜,但我們最終只需要一次“彈出”一個item,而不是創(chuàng)建整個list并返回.
對于句法說,我個人認(rèn)為yield更加簡潔,并且對于傳遞函數(shù)的用途表現(xiàn)的更好(譯者按:也就是代碼可讀性),我使用IEnumerable作為返回類型來通知調(diào)用者它可以被foreach循環(huán)并且返回數(shù)據(jù),而調(diào)用者現(xiàn)在可以自己決定它是否愿意將返回值存放到列表中,即使這會以性能作為代價。
在我提供的這個簡單例子中,也許你并不能發(fā)現(xiàn)很多使用yield的好處,然而,你可以在調(diào)用者需要取消遍歷所有的函數(shù)提供的內(nèi)容時節(jié)省很多不必要的工作,當(dāng)你在方法鏈接時使用yield,你可以省下的工作(時間)或許會成倍疊加。
Ayende已經(jīng)有了很棒的例子:using yield for a slick pipes & filters implementation,他甚至還講述了:version that is multi-threaded。這讓我覺得非常有趣.
最開始我對yield的保留意見是使用這個關(guān)鍵字或許會導(dǎo)致潛在的性能問題,但實際上,至今為止我還未能發(fā)現(xiàn)任何信息來說明關(guān)于yield對性能的影響,而我在上面提到提高性能的地方遠(yuǎn)遠(yuǎn)大于編譯器overhead那部分。
相關(guān)文章
C# Fiddler插件實現(xiàn)網(wǎng)站離線瀏覽功能
本文主要介紹了C# Fiddler插件實現(xiàn)網(wǎng)站離線瀏覽功能的原理與方法。具有很好的參考價值,下面跟著小編一起來看下吧2017-02-02C#實現(xiàn)統(tǒng)計100以內(nèi)所有素數(shù)的個數(shù)
這篇文章介紹了C#實現(xiàn)統(tǒng)計100以內(nèi)所有素數(shù)個數(shù)的方法,文中注釋非常詳細(xì),很適合新手學(xué)習(xí)。對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-11-11C#實現(xiàn)根據(jù)字節(jié)數(shù)截取字符串并加上省略號的方法
這篇文章主要介紹了C#實現(xiàn)根據(jù)字節(jié)數(shù)截取字符串并加上省略號的方法,比較實用的功能,需要的朋友可以參考下2014-07-07