IEnumerable<T>
是Java的Iterable<T>
的等價物。由於早期版本的C#沒有泛型,IEnumerable
是當時唯一可用的迭代器。你可以認爲它是一種IEnumerable<object>
。
大多數通用收集類型實現了IEnumerable<T>
,包括數組。通用變體需要實現非通用變體,因此大多數集合(通用或不通用)都實現IEnumerable
。
但是,這些迭代器不限於表示集合。他們提供的方法允許枚舉項目,這些方法也可以算法生成項目。例如,理論上 - 可以通過枚舉提供無限枚舉方形數字,而不需要在任何地方存儲這些數字。
在你的情況下,IEnumerable<MaliciousSmall> MaliciousCode
屬性可能會產生MaliciousSmall
對象從數據庫一枚接一枚作爲枚舉枚舉,而不先存儲在一個集合對象中。
實施IEnumerable<T>
您自己需要執行IEnumerator<T> GetEnumerator()
方法。它返回一個枚舉器對象,它需要實現方法bool MoveNext()
,void Dispose()
,void Reset()
和屬性T Current { get; }
。
你可以通過編寫很多代碼來實現這些接口,也可以使用C#的迭代器。迭代器使用大量的編譯器魔法在幕後自動創建枚舉數和枚舉數。參見:Iterators (C# and Visual Basic)。
以C#迭代的例子,讓我們實現您與他們的例子(我放棄了二傳,因爲它代表的方式在這裏):
public class PagedMalicious : Shared.Paged
{
public IEnumerable<MaliciousSmall> MaliciousCode
{
get
{
using (var conn = new SqlConnection("<my server connection>")) {
var cmd = new SqlCommand("SELECT name, number FROM myTable", conn);
conn.Open();
using (var reader = cmd.ExecuteReader()) {
while (reader.Read()) {
var maliciousSmall = new MaliciousSmall {
Name = reader.GetString(0),
Number = reader.GetInt32(1)
};
yield return maliciousSmall;
}
}
}
}
}
}
每次執行yield return
,控制是傳回給呼叫者,他得到下一個項目。 getter方法的狀態保持不變,其執行在此停止,直到調用者繼續迭代並需要下一個項目。當他這樣做時,執行會在yield return
聲明之後重新開始。
從這個例子可以看出,枚舉是以懶惰的方式評估的。以下代碼總結了整個表格的編號。這些項目永遠不會存儲在一個集合中;它們從數據庫中檢索並在枚舉時創建。這是一個優點,如果你有一百萬條記錄! (你可以使用一個SQL SUM
聚合函數在生產一段代碼,就這樣。)
var pagedMalicious = new PagedMalicious();
int sum = 0;
foreach (MaliciousSmall item in pagedMalicious.MaliciousCode) {
sum += item.Number;
}
'IEnumerable的'是完全等同於Java的'可迭代'。 –
SLaks