成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

詳解 C# 的 foreach 工作原理

原創(chuàng)
開(kāi)發(fā) 后端
作為開(kāi)發(fā)人員我們經(jīng)常會(huì)在程序中編寫(xiě) foreach 語(yǔ)句實(shí)現(xiàn)對(duì)類(lèi)型的遍歷,但是并不是所有的類(lèi)型都可以遍歷,這個(gè)知識(shí)點(diǎn)是絕大部分開(kāi)發(fā)成員所知曉的。但是類(lèi)型可以被 foreach 遍歷的依據(jù)是什么部分程序員并不清楚,下面我就通過(guò)舉例的方式來(lái)具體講解 foreach 原理。

[[346581]]

【51CTO.com原創(chuàng)稿件】作為開(kāi)發(fā)人員我們經(jīng)常會(huì)在程序中編寫(xiě) foreach 語(yǔ)句實(shí)現(xiàn)對(duì)類(lèi)型的遍歷,但是并不是所有的類(lèi)型都可以遍歷,這個(gè)知識(shí)點(diǎn)是絕大部分開(kāi)發(fā)成員所知曉的。但是類(lèi)型可以被 foreach 遍歷的依據(jù)是什么部分程序員并不清楚,下面我就通過(guò)舉例的方式來(lái)具體講解 foreach 原理。

在這里我們首先自定義一個(gè)類(lèi)型 Cat 并遍歷這個(gè)類(lèi)型:

  1. //定義 Cat 類(lèi)型 
  2. class Cat 
  3. //遍歷 Cat 
  4. class Program 
  5.    static void Main(string[] args) 
  6.   { 
  7.        Cat cat = new Cat(); 
  8.        foreach(var item in cat) 
  9.       { 
  10.            //more code 
  11.       } 
  12.   } 

我們運(yùn)行上述代碼后編譯器會(huì)提示錯(cuò)誤 “Cat” 不包含 “GetEnumerator” 的公共定義,因此 foreach 語(yǔ)句不能作用于 “Cat” 類(lèi)型的變量,由此錯(cuò)誤提示我們可以得知如果 Cat 類(lèi)型可以被 foreach 遍歷,那么 Cat 類(lèi)就必須實(shí)現(xiàn) GetEnumerator 方法。下面我們就在 Cat 類(lèi)中加入 GetEnumerator 方法。

  1. class Cat 
  2.    //加入 GetEnumerator 方法的實(shí)現(xiàn) 
  3.    public object GetEnumerator() 
  4.   { 
  5.        return null
  6.   } 

我們?cè)俅芜\(yùn)行代碼,這時(shí)程序出現(xiàn)如下兩個(gè)錯(cuò)誤提示:

  • foreach 要求 “Cat.GetEnumerator()”的返回類(lèi)型 “object”必須具有適當(dāng)?shù)墓?MoveNext 方法和公共 Current 屬性;

  • object 并不包含 “MoveNext” 的定義。

根據(jù)上述錯(cuò)誤提示我們可以推斷出 GetEnumerator 方法的返回值必須要有 MoveNext 方法和 Current 屬性。但是我們目前并不知道 GetEnumerator 方法的返回值類(lèi)型和 Current 屬性是否是只讀的,這種情況我們?cè)撛趺崔k呢?此時(shí)我們可以查看已經(jīng)支持 foreach 遍歷的類(lèi)型是怎么做的,下面的代碼段展示了 string 類(lèi)型是如何實(shí)現(xiàn)的(只列出了關(guān)鍵代碼)。

  1. //more code 
  2. public CharEnumerator GetEnumerator(); 
  3. //more code 
  4. pubic sealed class CharEnumerator:ICloneabe,IEnumerator<char>,IEnumerator,IDisposable 
  5.    public char Current {get;} 
  6.    //more code 
  7.    public bool MoveNext(); 
  8.    //more code 

根據(jù)上述代碼段我們仿寫(xiě)如下:

  1. class Cat 
  2.    public CatEnumerator GetEnumerator() 
  3.   { 
  4.        return new CatEnumerator(); 
  5.   } 
  6. class CatEnumerator 
  7.    public char Current {get;} 
  8.    public bool MoveNext() 
  9.   { 
  10.        return true
  11.   } 

這時(shí)我們編譯發(fā)現(xiàn)原來(lái)的錯(cuò)誤已經(jīng)消失了,程序編譯通過(guò)了。但是不要以為到這里就完了,Cat 類(lèi)僅僅包含這些是沒(méi)有任何意義的,這些內(nèi)容只是為了讓程序通過(guò)編譯而已,在實(shí)際開(kāi)發(fā)中我們遍歷的對(duì)象是一個(gè)序列,那么我們現(xiàn)在就在 Cat 類(lèi)中添加一個(gè)固定的序列:

  1. class Cat 
  2.    string[] datas=new string[]{"波斯貓","貍花貓","無(wú)毛貓","虎斑貓"}; 
  3.    public CatEnumerator GetEnumerator() 
  4.   { 
  5.        return new CatEnumerator(); 
  6.   } 

我們已經(jīng)添加了數(shù)據(jù)對(duì)象,那么 foreach 是如何訪問(wèn)到這個(gè)數(shù)據(jù)的呢?這時(shí)我們可以將數(shù)據(jù)對(duì)象通過(guò) GetEnumerator 方法作為迭代計(jì)數(shù)器對(duì)象(CatEnumerator)構(gòu)造函數(shù)的參數(shù)傳遞進(jìn)去,然后迭代計(jì)數(shù)器對(duì)象提供一個(gè)屬性將這些數(shù)據(jù)存儲(chǔ)起來(lái)。

  1. class Cat 
  2.    string[] datas=new string[]{"波斯貓","貍花貓","無(wú)毛貓","虎斑貓"}; 
  3.    public CatEnumerator GetEnumerator() 
  4.   { 
  5.        return new CatEnumerator(datas); 
  6.   } 
  7. class CatEnumerator 
  8.    //存儲(chǔ)數(shù)據(jù) 
  9.    private string[] datas; 
  10.    //帶參構(gòu)造函數(shù) 
  11.    public CatEnumerator(string[] datas) 
  12.   { 
  13.        this.datas=datas; 
  14.   } 
  15.    public char Current {get;} 
  16.    public bool MoveNext() 
  17.   { 
  18.        return true
  19.   } 

到目前為止我們已經(jīng)設(shè)置了遍歷的數(shù)據(jù),如果要將數(shù)據(jù)遍歷出來(lái)還需要一個(gè)下標(biāo)索引來(lái)讀取數(shù)組中的每個(gè)元素,并將每次讀取出來(lái)的元素值賦值給 Current 屬性。我們可以在迭代計(jì)數(shù)器對(duì)象中定義一個(gè) index 整型私有屬性作為下標(biāo)索引屬性,這里需要注意的是我們 index 這個(gè)屬性的默認(rèn)值為 -1 ,這一點(diǎn)是很多新手開(kāi)發(fā)人員比較容易出錯(cuò)的地方。既然有下標(biāo)了,我們?cè)诒闅v的時(shí)候下標(biāo)就必須是遞增變化,不斷指向下一個(gè)元素的位置直到到達(dá)數(shù)組的末端為止。這時(shí)我們就需要在 MoveNext 方法中進(jìn)行執(zhí)行下標(biāo)遞增的操作了,MoveNext 方法是一個(gè)返回值為 bool 類(lèi)型的方法,其目的是告知 foreach 當(dāng)前遍歷的數(shù)據(jù)對(duì)象是否存在還未遍歷到的元素,如果存在就返回 true 反之返回 false 遍歷結(jié)束。下面我們針對(duì)這一段所說(shuō)的內(nèi)容進(jìn)行代碼編寫(xiě)。

  1. class CatEnumerator 
  2.    //存儲(chǔ)數(shù)據(jù) 
  3.    private string[] datas; 
  4.    //帶參構(gòu)造函數(shù) 
  5.    public CatEnumerator(string[] datas) 
  6.   { 
  7.        this.datas=datas; 
  8.   } 
  9.    //數(shù)組下標(biāo) 
  10.    private int index=-1; 
  11.    //遍歷當(dāng)前元素 
  12.    public char Current  
  13.   { 
  14.        get 
  15.       { 
  16.            return datas[index]; 
  17.       } 
  18.   } 
  19.    public bool MoveNext() 
  20.   { 
  21.        index++; 
  22.        return index < datas.Length; 
  23.        return true
  24.   } 

到目前為止我們就編寫(xiě)了一個(gè)可以通過(guò) foreach 遍歷的類(lèi)型,這里有三點(diǎn)很重要:

  • GetEnumerator 方法的作用是 foreach 調(diào)用當(dāng)前需要遍歷的類(lèi)型的迭代計(jì)數(shù)器對(duì)象,該方法的返回類(lèi)型為用于foreach 遍歷的迭代計(jì)數(shù)器對(duì)象;

  • Current 屬性就是當(dāng)前遍歷到的對(duì)象;

  • MoveNext 方法促使迭代計(jì)數(shù)器對(duì)象的計(jì)數(shù)移動(dòng)到下一位。

通過(guò)前面所述的內(nèi)容,我們可知 foreach 遍歷主要有三個(gè)步驟:

  • foreach 調(diào)用當(dāng)前可遍歷類(lèi)型的 GetEnumerator 方法創(chuàng)建一個(gè)迭代計(jì)數(shù)器對(duì)象,并將要遍歷的數(shù)據(jù)傳遞給迭代計(jì)數(shù)器對(duì)象的構(gòu)造函數(shù)中;

  • 迭代計(jì)數(shù)器對(duì)象調(diào)用它 MoveNext 方法將所以小標(biāo)遞增 1 ,若下標(biāo)大于數(shù)據(jù)長(zhǎng)度則迭代完成;

  • MoveNext 方法返回 true 并返回 Current 屬性中存儲(chǔ)的數(shù)據(jù)。

以上三個(gè)步驟總結(jié)起來(lái)就是 獲取迭代計(jì)數(shù)器對(duì)象 >> 調(diào)用 MoveNext 方法 >> 獲取 Current 屬性

小技巧:在 c# 中如果要查看某個(gè)類(lèi)型是否支持 foreach 我們可以查看該類(lèi)型和該類(lèi)型的迭代計(jì)數(shù)器是否都實(shí)現(xiàn)了 IEnumerable 接口,因?yàn)?IEnumerable 接口中的就包含了 foreach 實(shí)現(xiàn)的原理和必須調(diào)用的成員。

作者簡(jiǎn)介

朱鋼,筆名喵叔,國(guó)內(nèi)某技術(shù)博客認(rèn)證專(zhuān)家,.NET高級(jí)開(kāi)發(fā)工程師,7年一線開(kāi)發(fā)經(jīng)驗(yàn),參與過(guò)電子政務(wù)系統(tǒng)和AI客服系統(tǒng)的開(kāi)發(fā),以及互聯(lián)網(wǎng)招聘網(wǎng)站的架構(gòu)設(shè)計(jì),目前就職于一家初創(chuàng)公司,從事企業(yè)級(jí)安全監(jiān)控系統(tǒng)的開(kāi)發(fā)。

【51CTO原創(chuàng)稿件,合作站點(diǎn)轉(zhuǎn)載請(qǐng)注明原文作者和出處為51CTO.com】

 

責(zé)任編輯:龐桂玉 來(lái)源: 51CTO
相關(guān)推薦

2009-07-31 18:39:31

C#中foreach引

2009-08-28 17:18:55

foreach循環(huán)

2011-03-11 09:41:17

JavaGC

2009-08-31 16:47:39

C#接口的定義

2009-01-19 10:26:02

C#Namespace.NET

2025-05-08 08:10:53

2009-09-03 17:40:25

C#發(fā)送短信

2009-09-07 16:13:56

C# MessageB

2009-07-30 18:20:21

C#繼承

2009-08-24 11:23:41

C# TimeLabe

2009-09-01 16:07:04

C#命名規(guī)約

2009-08-14 17:09:48

C#引用類(lèi)型

2009-09-02 19:12:37

C#遞歸

2009-09-02 11:02:57

C#動(dòng)態(tài)數(shù)組

2009-08-13 14:46:03

C#結(jié)構(gòu)體定義

2009-09-16 13:05:32

C#組件開(kāi)發(fā)

2009-09-17 16:34:24

C#組件類(lèi)

2009-08-26 15:25:06

.NET Framew

2009-08-25 17:43:17

C#串口監(jiān)聽(tīng)

2009-07-09 14:01:22

JVM工作原理
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 超碰激情 | 欧美激情在线播放 | 久久影音先锋 | 成人毛片在线视频 | 在线观看黄免费 | 91精品国产91久久久久久三级 | 日韩欧美亚洲 | 国产一区二区在线免费观看 | 成人1区2区 | 久久久这里都是精品 | 日本在线免费观看 | 日韩在线观看一区 | 免费亚洲网站 | 91精品久久久久久久久久入口 | 亚洲高清在线 | 久久青青| 国产三区在线观看视频 | 国产精品国产成人国产三级 | 日韩久久精品视频 | 成年免费在线观看 | 久久精品91 | 国产在线中文字幕 | 成人av播放 | 国产日韩视频 | 成人污污视频 | 欧美猛交| 亚洲天堂中文字幕 | 欧美在线小视频 | 国产精品视频久久久 | 亚洲欧美日韩在线 | 日本一二区视频 | 综合网视频 | 日韩一区二区三区在线观看 | 成年网站在线观看 | 久久国产精品一区二区三区 | 青青草视频网 | 精品成人一区 | 久草福利 | 狠狠综合网 | 91精品在线看 | 久久国产欧美日韩精品 |