C#中IEnumerable接口的使用
在 C# 中,IEnumerable<T>(讀作 “I Enumerable”)是 .NET 中表示“可枚舉集合”的核心接口。它是 LINQ、foreach 循環(huán)以及幾乎所有集合類型(如 List<T>、數(shù)組、Dictionary<TKey, TValue> 等)的基礎(chǔ)。
?? 簡單說:只要一個對象實(shí)現(xiàn)了 IEnumerable<T>,你就能用 foreach 遍歷它,也能用 LINQ 查詢它。
? 核心作用
IEnumerable<T> 的唯一職責(zé)就是:提供一種方式,讓你能逐個訪問集合中的元素,而不需要知道集合內(nèi)部是怎么存儲數(shù)據(jù)的。
這體現(xiàn)了面向?qū)ο笾械?“抽象” 和 “解耦” 思想。
?? 接口定義(簡化版)
public interface IEnumerable<out T>
{
IEnumerator<T> GetEnumerator();
}
public interface IEnumerator<out T> : IDisposable
{
T Current { get; } // 當(dāng)前元素
bool MoveNext(); // 移動到下一個元素,返回是否還有
void Reset(); // 重置(很少用)
}?? 你不需要手動實(shí)現(xiàn)這些(除非自定義集合),但要理解其工作原理。
? 最常見的使用場景
1.支持foreach循環(huán)
任何實(shí)現(xiàn) IEnumerable<T> 的類型都可以被 foreach 遍歷:
List<int> numbers = new List<int> { 1, 2, 3 };
// foreach 底層調(diào)用 numbers.GetEnumerator()
foreach (int n in numbers)
{
Console.WriteLine(n);
}2.作為方法返回類型(推薦?。?/h3>
當(dāng)你寫一個返回“一組數(shù)據(jù)”的方法時,優(yōu)先返回 IEnumerable<T> 而不是 List<T> 或數(shù)組:
public IEnumerable<string> GetActiveUsers()
{
yield return "Alice";
yield return "Bob";
// 或 return dbContext.Users.Where(u => u.IsActive).Select(u => u.Name);
}? 好處:
- 延遲執(zhí)行(Lazy Evaluation):調(diào)用方法時不會立即計算所有結(jié)果,而是在遍歷時逐個生成。
- 解耦:調(diào)用方不關(guān)心你是用
List、數(shù)組還是數(shù)據(jù)庫查出來的。 - 節(jié)省內(nèi)存:尤其適合大數(shù)據(jù)流或無限序列。
3.LINQ 查詢的基礎(chǔ)
所有 LINQ 方法(如 Where, Select, OrderBy)的輸入和輸出都是 IEnumerable<T>:
var result = numbers
.Where(x => x > 0) // 返回 IEnumerable<int>
.Select(x => x * 2); // 返回 IEnumerable<int>?IEnumerable<T>vsList<T>vs 數(shù)組
| 類型 | 是否可修改 | 是否知道長度 | 是否支持索引 | 延遲執(zhí)行 | 適用場景 |
|---|---|---|---|---|---|
| IEnumerable<T> | ? 只讀 | ? 不一定(需遍歷才知道) | ? 不支持 list[0] | ? 是 | 方法返回值、LINQ、通用遍歷 |
| List<T> | ? 可增刪改 | ? 有 .Count | ? 支持索引 | ? 否(數(shù)據(jù)已存在) | 需要頻繁修改或隨機(jī)訪問 |
| T[](數(shù)組) | ? 元素可改(但長度固定) | ? 有 .Length | ? 支持索引 | ? 否 | 性能敏感、大小固定的場景 |
?? 黃金建議:
- 參數(shù)類型:如果只需要遍歷,用 IEnumerable<T>
- 返回類型:優(yōu)先返回 IEnumerable<T>(除非調(diào)用方明確需要 List)
- 局部變量:如果需要修改或索引,用 List<T>
? 自定義IEnumerable<T>示例(了解即可)
public class Countdown : IEnumerable<int>
{
private int _start;
public Countdown(int start) => _start = start;
public IEnumerator<int> GetEnumerator()
{
for (int i = _start; i >= 0; i--)
yield return i; // yield 自動實(shí)現(xiàn) IEnumerator
}
// 非泛型版本(為了兼容舊代碼)
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
// 使用
foreach (int n in new Countdown(3))
{
Console.WriteLine(n); // 輸出: 3, 2, 1, 0
}?? 實(shí)際開發(fā)中,99% 的情況你不需要手動實(shí)現(xiàn) IEnumerable<T>,因?yàn)?List<T>、數(shù)組等已經(jīng)實(shí)現(xiàn)了它。
?? 常見誤區(qū)
? 誤區(qū)1:IEnumerable<T>是一個集合類
? 正解:它只是一個接口,描述“可以被遍歷”,本身不存儲數(shù)據(jù)。
? 誤區(qū)2:多次遍歷IEnumerable<T>總是安全的
? 正解:有些 IEnumerable<T> 只能遍歷一次(比如從數(shù)據(jù)庫流式讀取的結(jié)果)。
如果需要多次遍歷,調(diào)用 .ToList() 緩存結(jié)果:
var query = dbContext.Users.Where(u => u.Age > 18); // IQueryable<T> : IEnumerable<T>
// 第一次遍歷:OK
foreach (var u in query) { ... }
// 第二次遍歷:可能報錯(數(shù)據(jù)庫連接已關(guān)閉)
foreach (var u in query) { ... } // ? 危險!
// 安全做法:
var users = query.ToList(); // 立即執(zhí)行并緩存? 小結(jié)
| 關(guān)鍵點(diǎn) | 說明 |
|---|---|
| 是什么 | 表示“可被遍歷”的接口 |
| 核心方法 | GetEnumerator() → 返回一個“迭代器” |
| 最大優(yōu)勢 | 抽象遍歷邏輯,支持 foreach 和 LINQ |
| 最佳實(shí)踐 | 方法返回類型優(yōu)先用 IEnumerable<T> |
| 注意陷阱 | 警惕一次性枚舉器,必要時 .ToList() |
?? 一句話記住:
“IEnumerable<T> = 能被 foreach 的東西。”
如果你正在寫一個返回列表的方法,不妨試試返回 IEnumerable<T>,你會發(fā)現(xiàn)代碼更靈活、更符合 .NET 設(shè)計哲學(xué) ??
需要我?guī)湍惴治瞿硞€具體場景該用 IEnumerable<T> 還是 List<T> 嗎?
問題
什么是枚舉器?
枚舉其是一種允許遍歷集合元素的機(jī)制,他是一種指向集合中當(dāng)前元素的指針。
假設(shè)一個方法返回某種類型的集合,如果你不希望用戶修改此集合,如何最好地表達(dá)你的意圖?
可以將其作為Ienumerable或其他只讀集合類型返回。
到此這篇關(guān)于C#中IEnumerable接口的使用的文章就介紹到這了,更多相關(guān)C# IEnumerable接口內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C#多線程同步lock、Mutex的實(shí)現(xiàn)
本文主要介紹了C#多線程同步lock、Mutex的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2024-05-05
深入C#中使用SqlDbType.Xml類型參數(shù)的使用詳解
本篇文章是對在C#中使用SqlDbType.Xml類型參數(shù)的使用進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05
C#基于JsonConvert解析Json數(shù)據(jù)的方法實(shí)例
最近初接觸C#語言,發(fā)現(xiàn)JSON解析這塊和JAVA差異過大,下面這篇文章主要給大家介紹了關(guān)于C#基于JsonConvert解析Json數(shù)據(jù)的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-04-04
C#實(shí)現(xiàn)字符串進(jìn)制轉(zhuǎn)換方法匯總
這篇文章主要介紹了C#實(shí)現(xiàn)字符串進(jìn)制轉(zhuǎn)換方法匯總,給大家羅列了十幾種機(jī)制轉(zhuǎn)換問題,感興趣的朋友跟隨小編一起看看吧2022-11-11
C# ADO.NET 離線查詢的實(shí)現(xiàn)示例
這篇文章主要介紹了C# ADO.NET 離線查詢的實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-05-05
C#觀察者模式(Observer Pattern)實(shí)例教程
這篇文章主要介紹了C#觀察者模式(Observer Pattern),主要以一個實(shí)例的形式講述了C#觀察者模式的實(shí)現(xiàn)過程,詳細(xì)講述了接口的定義、通知及動作的實(shí)現(xiàn)方法,需要的朋友可以參考下2014-09-09

