植髮婉之C 迭代器

2022-06-27 12:48:16 字數 4326 閱讀 5347

植髮婉之c#迭代器

編寫的幾乎每個程式都需要迴圈訪問集合。 因此需要編寫**來檢查集合中的每一項。

還需建立迭代器方法,這些方法可為該類的元素生成迭代器(該物件遍歷容器,尤其是列表)。 這些方法可用於:

c# 語言提供了適用於這兩種方案的功能。 本文概述了這些功能。

列舉集合非常簡單:使用foreach關鍵字列舉集合,從而為集合中的每個元素執行一次嵌入語句:

foreach (var item in collection)

就這麼簡單。 若要迴圈訪問集合中的所有內容,只需使用foreach語句。 但foreach語句並非完美無缺。 它依賴於 .net core 庫中定義的 2 個泛型介面,才能生成迴圈訪問集合所需的**:ienumerableienumerator。 下文對此機制進行了更詳細說明。

這 2 種介面還具備相應的非泛型介面:ienumerableienumerator。 泛型版本是新式**的首要選項。

借助 c# 語言的另乙個強大功能,能夠生成建立列舉源的方法。 這些方法稱為「迭代器方法」 。 迭代器方法用於定義請求時如何在序列中生成物件。 使用yield return上下文關鍵字定義迭代器方法。

可編寫此方法以生成從 0 到 9 的整數序列:

getsingledigitnumbers()

">public ienumerable getsingledigitnumbers()

上方的**顯示了不同的yield return語句,以強調可在迭代器方法中使用多個離散yield return語句這一事實。 可以使用其他語言構造來簡化迭代器方法的**,這也是一貫的做法。 以下方法定義可生成完全相同的數字序列:

getsingledigitnumbers()

">public ienumerable getsingledigitnumbers()

不必從中選擇乙個。 可根據需要提供盡可能多的yield return語句來滿足方法需求:

getsingledigitnumbers()

">public ienumerable getsingledigitnumbers()

這是基本語法。 我們來看乙個需要編寫迭代器方法的真實示例。 假設你正在處理乙個 iot 專案,裝置感測器生成了大量資料流。 為了獲知資料,需要編寫乙個對每第 n 個資料元素進行取樣的方法。 通過以下小迭代器方法可實現此目的:

sample(this ienumerablesourcesequence, int interval)

}">public static ienumerablesample(this ienumerablesourcesequence, int interval)

}

迭代器方法有乙個重要限制:在同一方法中不能同時使用return語句和yield return語句。 不會編譯以下內容:

getsingledigitnumbers()

; return items;

}">public ienumerable getsingledigitnumbers()

; return items;

}

此限制通常不是問題。 可以選擇在整個方法中使用yield return,或選擇將原始方法分成多個方法,一些使用return,另一些使用yield return

可略微修改一下最後乙個方法,使其可在任何位置使用yield return

getsingledigitnumbers()

; foreach (var item in items)

yield return item;

}">public ienumerable getsingledigitnumbers()

; foreach (var item in items)

yield return item;

}

有時,正確的做法是將迭代器方法拆分成 2 個不同的方法。 乙個使用return,另乙個使用yield return。 考慮這樣一種情況:需要基於布林引數返回乙個空集合,或者返回前 5 個奇數。 可編寫類似以下 2 種方法的方法:

getsingledigitoddnumbers(bool getcollection)

private ienumerableiteratormethod()

}">public ienumerable getsingledigitoddnumbers(bool getcollection)

private ienumerable iteratormethod()

}

看看上面的方法。 第 1 個方法使用標準return語句返回空集合,或返回第 2 個方法建立的迭代器。 第 2 個方法使用yield return語句建立請求的序列。

foreach語句可擴充套件為使用ienumerableienumerator介面的標準用語,以便迴圈訪問集合中的所有元素。 還可最大限度減少開發人員因未正確管理資源所造成的錯誤。

編譯器將第 1 個示例中顯示的foreach迴圈轉換為類似於此構造的內容:

enumerator = collection.getenumerator();

while (enumerator.movenext())

">ienumerator enumerator = collection.getenumerator();

while (enumerator.movenext())

上述構造表示由 c# 編譯器版本 5 及更高版本生成的**。 在版本 5 之前,item變數的範圍有所不同:

enumerator = collection.getenumerator();

int item = default(int);

while (enumerator.movenext())

">// c# versions 1 through 4:

ienumerator enumerator = collection.getenumerator();

int item = default(int);

while (enumerator.movenext())

此範圍更改的原因在於:較早行為可能導致難以診斷出有關 lambda 表示式的 bug。 若要詳細了解 lambda 表示式,請參閱 lambda 表示式。

編譯器生成的確切**更複雜一些,用於處理getenumerator()返回的物件實現idisposable的情況。 完整擴充套件生成的**更類似如下:

} finally

}

列舉器的釋放方式取決於enumerator型別的特徵。 一般情況下,finally子句擴充套件為:

finally

但是,如果enumerator的型別為已密封型別,並且不存在從型別enumeratoridisposable的隱式轉換,則finally子句擴充套件為乙個空白塊:

finally

如果存在從型別enumeratoridisposable的隱式轉換,並且enumerator是不可為 null 的值型別,則finally子句擴充套件為:

finally

幸運地是,無需記住所有這些細節。foreach語句會為你處理所有這些細微差別。 編譯器會為所有這些構造生成正確的**。

大麥植髮婉之C vector容器

植髮費用?大麥植髮婉之c vector容器 我們在宣告陣列的時候,採用的是datatype arrayname len 的形式,陣列在分配之後,不能調整大小,刪除和插入資料時操作十分的繁瑣,雖然可以採用鍊錶,但是鍊錶的操作更麻煩,我們希望有更簡單的方法。與string類一樣,向量vector 同屬於...

大麥植髮婉之C語言巨集定義

植髮多少?大麥植髮婉之c語言巨集定義 巨集 macro 是預處理命令的一種,它允許用乙個識別符號來表示乙個字串。先看乙個例子 include define n 100 int main 執行結果 120該示例中的語句int sum 20 n n被100代替了。define n 100就是巨集定義,n...

大麥植髮婉之C 類的繼承與派生

植髮多少?大麥植髮婉之c 類的繼承與派生 繼承是物件導向程式設計中最重要的乙個概念。繼承允許我們根據乙個類來定義另乙個類,達到了 功能重用效果。當建立乙個類時,如果待建立的類與另乙個類存在某些共同特徵,程式設計師不需要全部重新編寫成員變數和成員函式,只需指定繼承另乙個類即可,被繼承的類稱為基類或父類...