C# --- IEnumerable 和 IEnumerator

C# --- IEnumerable 和 IEnumerator

  • IEnumerable
  • IEnumerator
  • IEnumerable 和 IEnumerator 的作用
  • 手動實現 IEnumerable
  • IEnumerable vs. IQueryable
  • 為什么有了ienumerator還需要ienumerable

IEnumerable

  • 在C#中,IEnumerable 是一個核心接口,用于表示一個可迭代的集合。它是實現迭代模式的基礎,允許你通過 foreach 循環遍歷集合中的元素
  • IEnumerable 是一個接口,屬于 System.Collections 命名空間。它的泛型版本 IEnumerable 位于 System.Collections.Generic 中。
  • 作用:標記一個對象可以被迭代(即支持 foreach 循環)。
  • 核心方法:GetEnumerator(),返回一個 IEnumerator 對象,用于逐個訪問集合中的元素。
public interface IEnumerable
{IEnumerator GetEnumerator();
}// 泛型版本(更常用):
public interface IEnumerable<out T> : IEnumerable
{IEnumerator<T> GetEnumerator();
}

IEnumerator

  • IEnumerator 是實際執行迭代的接口,相當于Java里的iterator, 他定義了三個關鍵方法:
  • MoveNext():移動到集合的下一個元素,返回 bool 表示是否成功。
  • Current:獲取當前元素的值。
  • Reset():重置迭代器到初始位置(通常不常用)
public interface IEnumerator
{bool MoveNext();object Current { get; }void Reset();
}// 泛型版本:
public interface IEnumerator<out T> : IEnumerator, IDisposable
{T Current { get; }
}

IEnumerable 和 IEnumerator 的作用

  • 統一迭代方式:任何實現 IEnumerable 的類型都可以用 foreach 遍歷。
  • 支持 LINQ:LINQ 的查詢操作(如 Where、Select)基于 IEnumerable,實現延遲執行。
  • 抽象集合類型:允許代碼操作抽象的集合(IEnumerable<T>),而非具體類型(如 List),提高靈活性。

手動實現 IEnumerable

using System;
using System.Collections;public class MyCollection : IEnumerable
{private int[] _data = { 1, 2, 3 };public IEnumerator GetEnumerator(){return new MyEnumerator(_data);}
}public class MyEnumerator : IEnumerator
{private int[] _data;private int _index = -1;public MyEnumerator(int[] data){_data = data;}public object Current => _data[_index];public bool MoveNext(){_index++;return _index < _data.Length;}public void Reset(){_index = -1;}
}// 使用:
var collection = new MyCollection();
foreach (var num in collection)
{Console.WriteLine(num); // 輸出 1, 2, 3
}

IEnumerable vs. IQueryable

  • IEnumerable:
    用于內存中集合(如 List、數組)。
    LINQ 操作由 C# 編譯器處理(如 Where 轉換為委托)。
  • IQueryable:
    用于外部數據源(如數據庫)。
    LINQ 操作轉換為表達式樹(如 SQL 查詢),由提供程序解析

為什么有了ienumerator還需要ienumerable

IEnumerable:

  • 角色:表示一個集合是“可迭代的”。
    核心功能:通過 GetEnumerator() 方法返回一個迭代器(IEnumerator 對象)。
  • 意義:提供統一的接口,讓所有集合類型(如數組、List、自定義集合)都能被 foreach 遍歷。

IEnumerator:

  • 角色:實際控制迭代過程(移動指針、獲取當前元素)。
  • 核心功能:通過 MoveNext() 和 Current 實現逐個元素的遍歷。
  • 意義:封裝迭代狀態(如當前索引),確保多次遍歷互不干擾

場景假設

  • 假設一個集合類直接實現 IEnumerator, 如果兩個 foreach 同時遍歷同一個 BadList 實例,它們的 _index 會互相干擾:無法支持并發迭代:同一實例的迭代狀態會被覆蓋
public class BadList : IEnumerator<int>
{private int[] _data = { 1, 2, 3 };private int _index = -1;public int Current => _data[_index];object IEnumerator.Current => Current;public bool MoveNext(){_index++;return _index < _data.Length;}public void Reset() => _index = -1;public void Dispose() { }
}
var badList = new BadList();
foreach (var num in badList) { /* 第一次遍歷 */ } // 輸出 1,2,3
foreach (var num in badList) { /* 第二次遍歷 */ } // 無輸出(索引已到末尾)

正確做法:IEnumerable + IEnumerator

public class GoodList : IEnumerable<int>
{private int[] _data = { 1, 2, 3 };public IEnumerator<int> GetEnumerator(){// 每次調用返回一個新的迭代器return new GoodListEnumerator(_data);}// 顯式實現非泛型接口IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}public class GoodListEnumerator : IEnumerator<int>
{private int[] _data;private int _index = -1;public GoodListEnumerator(int[] data) => _data = data;public int Current => _data[_index];object IEnumerator.Current => Current;public bool MoveNext(){_index++;return _index < _data.Length;}public void Reset() => _index = -1;public void Dispose() { }
}
  • 狀態隔離:每次 foreach 會調用 GetEnumerator() 生成新的 IEnumerator 實例,確保每次遍歷獨立。
  • 并發安全:多個遍歷操作互不影響。
  • 簡化代碼:foreach 自動管理迭代器生命周期(調用 Dispose())。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/76025.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/76025.shtml
英文地址,請注明出處:http://en.pswp.cn/web/76025.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

鏡舟科技助力某大型電網企業破解數據架構升級難題,打造國產化湖倉標桿

在 “十四五” 規劃全面推進國產化替代的背景下&#xff0c;某大型電網企業聯合鏡舟科技與騰訊云&#xff0c;基于全球領先的開源分析型數據庫 StarRocks 及騰訊 TBDS 大數據平臺&#xff0c;構建電力行業國產化湖倉一體架構。該項目實現 PB 級電力數據的統一管理&#xff0c;為…

Spark-SQL核心編程3

數據加載與保存 通用方式&#xff1a; SparkSQL 提供了通用的保存數據和數據加載的方式。這里的通用指的是使用相同的API&#xff0c;根據不同的參數讀取和保存不同格式的數據&#xff0c;SparkSQL 默認讀取和保存的文件格式為parquet 數據加載方法&#xff1a; spark.read.lo…

使用HTML + CSS + JS,編寫一個臺球追分計分器

目錄 一.代碼 二.效果展示 三.該計分器的優點 一.代碼 <!DOCTYPE html> <html lang"zh-CN"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><…

LLM小白自學筆記:1.兩種指令微調

一、LoRA 簡單來說&#xff0c;LoRA不直接調整個大模型的全部參數&#xff08;那樣太費資源&#xff09;&#xff0c;而是在模型的某些層&#xff08;通常是注意力層&#xff09;加個“旁路”——兩個小的矩陣&#xff08;低秩矩陣&#xff09;。訓練時只更新這倆小矩陣&#x…

2026《數據結構》考研復習筆記一(C++基礎知識)

C基礎知識復習 一、數據類型二、修飾符和運算符三、Lambda函數和表達式四、數學函數五、字符串六、結構體 一、數據類型 1.1基本類型 基本類型 描述 字節&#xff08;位數&#xff09; 范圍 char 字符類型&#xff0c;存儲ASCLL字符 1&#xff08;8位&#xff09; -128…

基于骨骼識別的危險動作報警分析系統

基于骨骼識別的危險動作報警分析系統 【包含內容】 【一】項目提供完整源代碼及詳細注釋 【二】系統設計思路與實現說明 【三】基于骨骼識別算法的實時危險行為預警方案 【技術棧】 ①&#xff1a;系統環境&#xff1a;Windows 10/11、macOS Ventura、Ubuntu 20.04 ②&#x…

【雙指針】四數之和(medium)

四數之和&#xff08;medium&#xff09; 題?描述&#xff1a;解法&#xff08;排序 雙指針&#xff09;算法思路&#xff1a; C 算法代碼&#xff1a;Java 算法代碼&#xff1a; 題?鏈接&#xff1a;18. 四數之和 題?描述&#xff1a; 給你?個由 n 個整數組成的數組 num…

Flask+Influxdb+grafna構建電腦性能實時監控系統

Influx下載地址&#xff0c;這里下載了以下版本influxdb-1.8.5_windows_amd64.zip 運行前需要先啟動Influx數據庫&#xff1a; 管理員方式運行cmd->F:->cd F:\influxdb\influxdb-1.8.5-1->influxd -config influxdb.conf&#xff0c;以influxdb.conf配置文件啟動數…

如何在Keil中配置國民技術N32G系列MCU開發環境

如何在Keil及Jlink中搭建國民技術N32G系列MCU開發環境 根據自己的MCU型號&#xff08;我這里的型號是N32G452REL7&#xff09;訪問國民技術官網&#xff0c;依次從N32G通用MCU-技術資源-固件和軟件-軟件開發套件&#xff0c;獲取對應MCU型號的SDK&#xff0c;也可點擊這里從網盤…

微軟承認Win11出現極端錯誤,只能強制關機或重裝系統

最近&#xff0c;不少使用 Windows 11 的用戶反映&#xff0c;在系統更新后&#xff0c;“Windows Hello”突然失效&#xff0c;原本便捷的人臉識別和PIN登錄功能統統無法使用。更糟的是&#xff0c;有人在重置系統后直接被擋在系統門外&#xff0c;這讓人不禁發問&#xff1a;…

【android bluetooth 協議分析 02】【bluetooth hal 層詳解 1】【uart 介紹】

一、什么是 UART&#xff1f; UART&#xff08;Universal Asynchronous Receiver/Transmitter&#xff09; 是一種 串行通信協議&#xff0c;它的特點是通信時不需要專門的時鐘信號&#xff08;叫做“異步”通信&#xff09;&#xff0c;常用于兩個設備之間的簡單數據通信&…

天元證券|奶粉行業結構性回暖 乳企競速全齡化、國際化

在過去幾年中&#xff0c;中國嬰配粉市場經歷了量價齊增&#xff0c;量減價增&#xff0c;量減價減的三個周期。歷經多年行業深度洗牌與競爭格局重塑&#xff0c;2024年中國嬰配粉市場回暖態勢愈發清晰可辨。 日前&#xff0c;包括中國飛鶴、澳優、健合集團在內的多家奶粉股披露…

第3.1節 調用鏈路分析簡介

調用鏈路&#xff08;Call Chain / Call Path&#xff09; 是程序在執行過程中&#xff0c;按照調用順序形成的函數、模塊或組件之間的依賴關系鏈條&#xff0c;完整記錄了從程序入口到當前執行點的動態調用路徑。它反映了代碼執行的邏輯流程&#xff0c;是分析程序行為、調試問…

System.Security.Cryptography.CryptographicException“填充無效,無法被移除。”

這個異常通常發生在以下幾種情況&#xff1a; 1.密文損壞&#xff1a;密文在傳輸或存儲過程中被篡改或損壞。 2.密鑰不匹配&#xff1a;用于解密的密鑰與加密時使用的密鑰不同。 3.填充模式不匹配&#xff1a;加密時使用的填充模式與解密時指定的填充模式不一致。 4.使用了不正…

【網絡入侵檢測】Suricata之數據包內容匹配

【作者主頁】只道當時是尋常 【專欄介紹】入侵檢測。專注網絡、主機安全&#xff0c;歡迎關注與評論。 1. 概要 本文詳細介紹了網絡入侵檢測系統&#xff08;如 Suricata&#xff09;中用于檢查數據包或流有效載荷的 Payload 關鍵字。content 用于匹配數據包內容&#xff0c;默…

Spring Boot 整合 Redis 實現點贊功能:從基礎到實踐

在當今互聯網應用開發中&#xff0c;點贊功能幾乎成為了各類內容平臺的標配。它不僅能增加用戶與內容之間的互動&#xff0c;還能直觀地反映內容的受歡迎程度。本文將詳細介紹如何使用 Spring Boot 整合 Redis 來實現一個簡單的文章點贊功能&#xff0c;讓你輕松掌握這一實用技…

openGauss DataVec + Dify,快速搭建你的智能助手平臺

在當今數字化和智能化的時代&#xff0c;大語言模型&#xff08;LLM&#xff09;的應用正以前所未有的速度改變著各個領域的工作方式和用戶體驗。Dify 作為一個開源的大語言模型應用開發平臺&#xff0c;為開發者們提供了便捷且強大的工具&#xff0c;助力構建從基礎智能體到復…

OpenLayers:extent與view extent 介紹

一、范圍的概念 1.什么是范圍&#xff1f; 在Openlayers中范圍&#xff08;Extent&#xff09;是用于表示地理空間區域的一種概念。它通常由一個數字數組構成&#xff0c;數組中的內容為&#xff1a;[最小x坐標&#xff0c;最小y坐標&#xff0c;最大x坐標&#xff0c;最大y坐…

can‘t set boot order in virtualbox

Boot order setting is ignored if UEFI is enabled https://forums.virtualbox.org/viewtopic.php?t99121 如果勾選EFI boot order就是灰色的 傳統BIOS就是可選的 然后選中任意介質&#xff0c;通過右邊的上下箭頭調節順序&#xff0c;最上面的應該是優先級最高的 然后就…

如何在 Kali 上解決使用 evil-winrm 時 Ruby Reline 的 quoting_detection_proc 警告

在使用 Kali Linux 運行 Ruby 工具&#xff08;例如 evil-winrm&#xff09;時&#xff0c;你可能會遇到以下警告&#xff1a; Warning: Remote path completions is disabled due to ruby limitation: undefined method quoting_detection_proc for module Reline這個警告會導…