C 迭代器原理詳解

2021-09-10 08:36:55 字數 2658 閱讀 5167

迭代器模式提供乙個方法順序訪問乙個聚合物件中的各個元素,而又不暴露其內部的表示。

在c#中,可以通過ienumerable和ienumerator來實現這個模式。首先,我按照這兩個介面完成了迭代器模式的實現:迭代器模式案例

在這個example中,分別實現了這兩個類

public class dinermenu : ienumerable
public class dinermenuiterator : ienumerator
其中,dinermenu是需要可以被遍歷的類,然後建立了dinermenuiterator用於遍歷dinermenu。(具體實現過程不贅述,可以參考這篇文章: ,或者參考head first中的迭代器模式章節)我們可以看到,實現起來還是比較繁瑣的,尤其是如果專案中有許多類需要支援迭代器模式時。所以,在c#2中,提供了一種yield語法糖,來幫助我們化簡這個實現。

public ienumerator getenumerator()

}

只需要如上寥寥幾行**就可以實現了,是不是使用起來很方便?下面我們來分析一下這個語法糖的內部實現。依舊是先寫一段盡量簡潔的實驗**:

public ienumerator getenumerator()

}

然後使用ilspy進行反編譯。檢視il**,如下圖所示:

除去我們自己的getenumerator方法外,編譯器給我們建立了乙個新類"d__1",檢視getenumerator方法,發現已經發生了改變:

這個函式現在做了三件事:

轉化成c#**也就是:

getenumerator_d_1 enumerator = new getenumerator_d_1(0);

enumerator._4__this = this;

return enumerator;

也就是說原來我們寫的那幾行**已經全部消失不見了,因此在這裡猜測是被轉移到了這個新建立的類中,下面來檢視一下這個類的具體實現,首先,這個類實現了三個介面ienumerator,ienumerator,idisposable:

這個類中有如下引數,為了方便,下文將分別標記為m_state,m_current,_4__this,m_5__1:

首先,構造器:

public getenumerator_d_1(int state)

其中,state即為上文中的0;

接著,我們可以看到,絕大多數邏輯都會在movenext()中實現,下面是除去movenext()之外的一些方法及我大致翻譯成的c#**

public void dispose()

public void reset()

private object get_current()

public object current

}

在movenext()中,我們可以找到之前寫在getenumerator()中的邏輯:

.method private final hidebysig newslot virtual 

instance bool movenext () cil managed

// end of method 'd__1'::movenext

翻譯成c#**大致是如下意思:

public bool movenext()

case 1:

}if(m_5_1 < 3)

return false;

}

我們在前面提到,構造器一開始是將m_state賦值為0的,所以,第一次呼叫這個方法時,會進入case 0,完成一次初始化,然後,m_current賦值,m_state置為1,返回。此後每次呼叫,m_5_1都會++。也就是說,原本的**在這裡會以狀態機的方式重新構成,並且使用m_state來記錄狀態機狀態。

根據以上分析,大致得出,yield return在編譯時會將這塊語句去掉,然後生成乙個enumerator類,然後當呼叫getenumerator()方法時會建立乙個enumerator返回,同時,原本寫在getenumator中的邏輯**會以狀態機的形式轉移到movenext()函式中,通過m_5_1變數來記錄當前遍歷的位置、m_state來維護這個狀態機。

1、head first迭代器模式章節

2、詳解c# 迭代器

3、狀態機/迭代器/linq/協程

C 迭代器(STL迭代器)iterator詳解

要訪問順序容器和關聯容器中的元素,需要通過 迭代器 iterator 進行,迭代器是乙個變數,相當於容器和操作容器的演算法之間的中介。迭代器可以指向容器中的某個元素,通過迭代器就可以讀寫它指向的元素。從這一點上看,迭代器和指標型別。迭代器按照定義方式分為以下四種 正向迭代器,定義方式 容器類名 it...

C 迭代器(Iterator)詳解

迭代器 iterator 的介紹 背景 指標可以用來遍歷儲存空間連續的資料結構,但是對於儲存空間費連續的,就需要尋找乙個行為類似指標的類,來對非陣列的資料結構進行遍歷。定義 迭代器是一種檢查容器內元素並遍歷元素的資料型別。迭代器提供對乙個容器中的物件的訪問方法,並且定義了容器中物件的範圍。迭代器 i...

C 迭代器(Iterator)詳解

1 迭代器 iterator 的介紹 背景 指標可以用來遍歷儲存空間連續的資料結構,但是對於儲存空間非連續的,就需要尋找乙個行為類似指標的類,來對非陣列的資料結構進行遍歷。定義 迭代器是一種檢查容器內元素並遍歷元素的資料型別。迭代器提供對乙個容器中的物件的訪問方法,並且定義了容器中物件的範圍。迭代器...