C 中foreach的實現原理

2021-07-29 22:16:05 字數 3723 閱讀 5944

在**foreach如何內部如何實現這個問題之前,

我們需要理解兩個

c#裡邊的介面,

ienumerable與ie

numerator. 在c#

裡邊的遍歷集合時用到的相關類中,

ienumerable

是最基本的介面。這是乙個可以進行泛型化的介面,比如說

ienumerable.

在微軟的

.net

推出了這兩個介面後,才有了

foreach

的用法,可以說,

foreach

是建立在這兩個介面的基礎之上的,

foreach

的前提是其裡邊的容器要實現了

ienumerable

介面。

ienumerable

這個介面裡邊定義的內容非常簡單,最重要的就是裡邊有乙個抽象方法getenumerator. ienumerable

的意思是這個集合是可以遍歷的,而這個

getenumerator

方法返回的

ienumerator

的就是乙個遍歷器,用這個工具來遍歷這個類。如果說ienumerable

是一瓶香檳,那麼

ienumerator就是乙個開瓶器。

在實現這個

ienumerable

介面的時候,必須要實現這個getenumerator方法,要返回乙個例項化的ienumorator. 

下面來介紹一下這個

ienumorator

介面。這個介面中定義的內容也很簡單,包括

current

,就是返回這個遍歷工具所指向的那個容器的當前的元素,

movenext 方

法就是指向下乙個元素,當遍歷到最後沒有元素時,返回乙個

false

.當我們實現乙個

ienumerable

類的時候,我們的目的就應該是遍歷這個集合,所以同時我們要實現

ienumerator

這個工具類,定義我們自己的邏輯來告訴

clr我們怎麼去遍歷這個集合。 

下面是乙個簡單的例子,來說明一下這兩個介面的用法。

[csharp]view plain

copy

// person類包括兩個屬性。

public

class

person  

public

string

firstname;  

public

string

lastname;  

}  //people類就是person的集合,裡邊使用了乙個陣列把單個的物件存在這個陣列當中。而且因為實現了

//ienumerable介面,所以要實現getenumerator方法,返回乙個實現了ienumerator的類。

public

class

people : ienumerable  

}  public

peopleenum getenumerator()  

}  // 這裡我們需要定義一套邏輯去遍歷上邊的集合。

public

class

peopleenum : ienumerator  

public

bool

movenext()  

public

void

reset()  

object

ienumerator.current  

}  public

person current  

catch

(indexoutofrangeexception)  

}  }  }  

class

;  people peoplelist = new

people(peoplearray);  

//在這裡使用foreach就可以遍歷這個集合了,因為它實現了ienumerable介面。

foreach

(person p 

inpeoplelist)  

console.writeline(p.firstname + " "

+ p.lastname);  

}  }  

/* this code produces output similar to the following:

** john smith

* jim johnson

* sue rabon**/

如果說,

foreach

後台的邏輯是這麼實現的?大概是這個樣子的。上邊的**會被

clr翻譯成這樣。

[csharp]view plain

copy

foreach

(person p 

inpeoplelist)  

console.writeline(p.firstname + " "

+ p.lastname);  

//翻譯成

ienumerator enumerator = (peoplelist).getenumerator();  

try  

}  finally  

附加:關於ienumerable與orm框架聯合使用時候的延遲載入問題,以及resharper對於此介面mutiple enumeration警告問題

使用ienumerable

的時候,

resharper

經常會提示這個問題?這個問題意思是,這個集合物件可能會返回不同的遍歷結果。

因為ienumerable

另外乙個功能就是存放

sql一類的查詢邏輯,注意,這裡指的是查詢邏輯,而不是真正的查詢結果,也就是延遲載入。以下邊的例子為例,可能

objects

中存放的是

sql查詢邏輯。當第一次呼叫

any()

方法的時候,會呼叫

sql語句查詢到資料庫中的結果,這時候是有一條資料的。但是

objects

呼叫first()

方法來獲取這個記錄的時候,可能這時候的資料庫已經被其他的程式改了,沒有資料了,這時候就出現了

dirty data

的問題。所以,為了資料的一致性,需要在使用

ienumeralbe

的時候,呼叫

.tolist()

方法把這些內容存放在乙個個實實在在的容器中,這樣就前後一致了。

還有就是從**效能角度考慮,每次都呼叫一下資料庫會很慢,所以乾脆一下全部把資料庫中符合條件的結果放到記憶體l

ist中,用的時候直接從記憶體中拿就快多了。

[csharp]view plain

copy

public

list<

object

> foo(ienumerable<

object

> objects)    

ienumerable

在一些orm

框架中實現了延遲載入的功能。比如說,在框架自己定義的容器物件中,實現了特定的

ienumerator

介面,在

movenext

中指定邏輯,連線資料庫,獲取物件等。

注:c#中dictionary字典類介紹:

C 中foreach的實現原理

c 中foreach的實現原理 在 foreach如何內部如何實現這個問題之前,我們需要理解兩個c 裡邊的介面,ienumerable 與 ienumerator.在c 裡邊的遍歷集合時用到的相關類中,ienumerable是最基本的介面。這是乙個可以進行泛型化的介面,比如說ienumerable....

C 中foreach的原理

結構篇 foreach 語句為陣列或物件集合中的每個元素重複乙個嵌入語句組。foreach 語句用於迴圈訪問集合以獲取所需資訊,但不應用於更改集合內容以避免產生不可預知的 此語句的形式如下 foreach type identifier in expression statement 其中 type...

GCC中實現c 的 foreach

boost 1.34中提供了foreach,只可惜這個實現也太醜陋了,根本沒有實用價值。其實在gcc中實現foreach是相當簡單的,因為 gcc 提供了typeof 關鍵字。這裡提供乙個實現,與boost不同,用的是 iterator 的概念。用法 vector string vec foreac...