手機(jī)app微信網(wǎng)站品牌策劃運(yùn)營公司
文章目錄
- 前言
- 一、yield 關(guān)鍵字的語法形式及使用場景
- (一)yield return
- (二)yield break
- 二、yield 關(guān)鍵字的工作原理
- 三、yield 關(guān)鍵字的優(yōu)勢與應(yīng)用場景
- (一)優(yōu)勢
- (二)應(yīng)用場景
前言
??在 C# 中,yield 關(guān)鍵字是一個(gè)非常獨(dú)特且強(qiáng)大的語言特性,它主要用于迭代器塊(Iterator Block)中,能夠讓開發(fā)者以一種簡潔高效的方式實(shí)現(xiàn)自定義的可迭代類型,輕松地生成并返回一個(gè)序列的值,而無需像傳統(tǒng)方式那樣創(chuàng)建一個(gè)完整的集合對象來存儲所有要返回的數(shù)據(jù)。簡單來說,yield 關(guān)鍵字幫助我們實(shí)現(xiàn)了一種 “按需生成” 數(shù)據(jù)的機(jī)制,特別適用于處理大數(shù)據(jù)量或者無限序列的情況,避免了一次性占用大量內(nèi)存空間。
??例如,想象要生成一個(gè)包含所有自然數(shù)的序列,如果不使用 yield 關(guān)鍵字,可能需要先創(chuàng)建一個(gè)非常大的數(shù)組或者列表來存儲這些數(shù),這顯然會消耗大量內(nèi)存且效率低下。而借助 yield 關(guān)鍵字,就可以在需要的時(shí)候逐個(gè)生成這些自然數(shù),不會造成不必要的內(nèi)存開銷。
一、yield 關(guān)鍵字的語法形式及使用場景
(一)yield return
??yield return 語句是 yield 關(guān)鍵字最常見的用法,它用于從迭代器塊中返回一個(gè)值,并且會 “記住” 當(dāng)前的執(zhí)行位置,下次調(diào)用迭代器繼續(xù)執(zhí)行時(shí),會從這個(gè)位置接著往下執(zhí)行,繼續(xù)生成下一個(gè)值,以此類推,直到迭代結(jié)束。
??以下是一個(gè)簡單的示例,定義了一個(gè)方法來生成斐波那契數(shù)列(這里只生成有限項(xiàng)):
using System;
using System.Collections.Generic;public static IEnumerable<int> FibonacciSequence(int count)
{int a = 0, b = 1;for (int i = 0; i < count; i++){yield return a;int temp = a;a = b;b = temp + b;}
}
??在上述代碼中,FibonacciSequence 方法返回一個(gè)實(shí)現(xiàn)了 IEnumerable 接口的可迭代序列,通過 yield return 語句,每次循環(huán)時(shí)返回斐波那契數(shù)列中的一項(xiàng)。例如,我們可以這樣調(diào)用并遍歷這個(gè)序列:
foreach (int num in FibonacciSequence(10))
{Console.Write(num + " ");
}
??輸出結(jié)果將會是斐波那契數(shù)列的前 10 項(xiàng):0 1 1 2 3 5 8 13 20 34。在這個(gè)過程中,每次 foreach 循環(huán)迭代時(shí),就會觸發(fā) yield return 執(zhí)行,生成下一個(gè)數(shù)列的值,并不會一次性把整個(gè)斐波那契數(shù)列都計(jì)算并存儲好再返回。
(二)yield break
??yield break 語句用于終止迭代器的執(zhí)行,提前結(jié)束整個(gè)迭代過程。通常在滿足某些特定條件,不需要再繼續(xù)生成后續(xù)數(shù)據(jù)時(shí)使用。
??例如,修改上面的斐波那契數(shù)列生成方法,假設(shè)當(dāng)生成的數(shù)大于 100 時(shí)就停止生成,代碼可以修改為如下:
using System;
using System.Collections.Generic;public static IEnumerable<int> FibonacciSequence(int count)
{int a = 0, b = 1;for (int i = 0; i < count; i++){if (a > 100){yield break;}yield return a;int temp = a;a = b;b = temp + b;}
}
??在這個(gè)示例中,一旦生成的斐波那契數(shù) a 大于 100,就會執(zhí)行 yield break,迭代器停止工作,后續(xù)的元素就不會再被生成和返回了。
二、yield 關(guān)鍵字的工作原理
??當(dāng)使用 yield 關(guān)鍵字的迭代器方法被調(diào)用時(shí)(比如在 foreach 循環(huán)中調(diào)用),編譯器會自動(dòng)生成一個(gè)狀態(tài)機(jī)(State Machine)來管理迭代的過程。這個(gè)狀態(tài)機(jī)負(fù)責(zé)跟蹤迭代器的當(dāng)前執(zhí)行位置、局部變量的值等信息,每次遇到 yield return 時(shí),它會保存當(dāng)前的狀態(tài),返回相應(yīng)的值給調(diào)用者,等到下一次調(diào)用繼續(xù)迭代時(shí),又能恢復(fù)到之前保存的狀態(tài),接著往下執(zhí)行,繼續(xù)生成下一個(gè)值。
??從內(nèi)存管理角度來看,由于數(shù)據(jù)是按需生成的,在某個(gè)時(shí)刻只有當(dāng)前正在生成和返回的值會占用內(nèi)存,而不是一次性將整個(gè)序列的數(shù)據(jù)都加載到內(nèi)存中,這對于處理大量數(shù)據(jù)或者無限序列的情況非常有優(yōu)勢,大大節(jié)省了內(nèi)存資源,同時(shí)也提升了程序的性能和響應(yīng)速度。
三、yield 關(guān)鍵字的優(yōu)勢與應(yīng)用場景
(一)優(yōu)勢
內(nèi)存高效: 避免了提前創(chuàng)建和存儲大量的數(shù)據(jù),只在需要的時(shí)候生成并返回值,有效減少了內(nèi)存占用,特別是對于大數(shù)據(jù)集或者無限長的序列,這種優(yōu)勢更為明顯。
代碼簡潔: 能夠以簡潔的代碼實(shí)現(xiàn)復(fù)雜的可迭代邏輯,相較于傳統(tǒng)的通過創(chuàng)建集合對象、手動(dòng)管理索引等方式來生成序列數(shù)據(jù),使用 yield 關(guān)鍵字的代碼更加清晰、易讀和易于維護(hù)。
靈活性高: 可以方便地根據(jù)不同的條件動(dòng)態(tài)地生成數(shù)據(jù)序列,比如根據(jù)用戶輸入、運(yùn)行時(shí)的配置等因素實(shí)時(shí)調(diào)整生成的數(shù)據(jù)內(nèi)容,而不需要對整個(gè)數(shù)據(jù)生成邏輯進(jìn)行大規(guī)模重構(gòu)。
(二)應(yīng)用場景
處理大數(shù)據(jù)集合: 比如從數(shù)據(jù)庫中查詢大量的數(shù)據(jù)記錄,不想一次性將所有記錄都加載到內(nèi)存中,可以使用 yield 關(guān)鍵字實(shí)現(xiàn)一個(gè)迭代器,每次從數(shù)據(jù)庫中讀取一條記錄并返回,這樣可以在內(nèi)存有限的情況下高效地處理大量數(shù)據(jù)。
生成無限序列: 像生成自然數(shù)序列、質(zhì)數(shù)序列等無限長的序列時(shí),使用 yield 關(guān)鍵字能夠讓程序可以持續(xù)生成后續(xù)的值,而不會因?yàn)閮?nèi)存耗盡而崩潰,同時(shí)調(diào)用者可以根據(jù)自己的需要獲取指定數(shù)量的元素,具有很高的靈活性。
遍歷復(fù)雜的數(shù)據(jù)結(jié)構(gòu): 當(dāng)需要遍歷一些復(fù)雜的數(shù)據(jù)結(jié)構(gòu)(如樹形結(jié)構(gòu)、圖結(jié)構(gòu)等),并按照特定順序返回節(jié)點(diǎn)的值時(shí),利用 yield 關(guān)鍵字可以輕松地實(shí)現(xiàn)深度優(yōu)先遍歷、廣度優(yōu)先遍歷等不同的遍歷邏輯,將遍歷過程中節(jié)點(diǎn)的值逐個(gè)返回給調(diào)用者。