上一章節將的是如何使用選擇判斷語法,今天講的大家都熟悉的循環語句。我想大家對while,do..while,for,foreach都不陌生吧,但在於性能方面上似乎又覺得陌生? 到底哪個性能更高,效率更快呢。讓我們做個測試吧。
其實在while,do...while,for這三個循環體中效率是一樣,爲什麼會這麼說? 其實在執行這三個循環過程中所執行的指令數是一樣,只不過執行過程中步驟,內容有細微的不一樣。讓我們看看下面代碼:
public void Test_While() {
int n = 10;
while (n-- > 0) {
//執行內容
}
}
public void Test_For() {
for (int n = 10; n > 0; n--) {
//執行內容
}
}
public void Test_doWhile() {
int n = 10;
do {
//執行內容
} while (--n > 0);
}
小計:從以上代碼來上,for語法最近簡潔,也最複雜;while語法最簡單;do..while執行方式比較特別,先執行內容後判斷條件,無論如何至少執行一次以上。在效率方面上while,do..while循環體方法中所執行的指令是一樣,而for會比前兩種多執行一次。在我們仔細觀察看着個多執行一次指令是因爲要聲明實例化n。那麼其實在執行whilehuo do..while之前也是對n先進性實例化。所以三者執行次數是一樣,執行效率同時也是一樣。至於會影響效率的是執行內容。
而foreach在效率方面上與前三種有所不同。首先我們先看看foreach工作原理——在foreach循環中,迭代集合collectionObject的過程如下:
- 調用collectionObject.GetEnumerator(),返回一個IEnumerator引用。這個方法可以通過IEnumerable接口的實現代碼來獲得。但這是可選的。
- 調用返回的IEnumerator接口的MoveNext()方法。
- 如果MoveNext()方法返回true,就使用IEnumerator接口的Current屬性獲取對象的一個引用,用於foreach循環。
- 重複前面兩步,直到MoveNext()方法返回false爲止,此時循環停止。
接下來我們看看for 與foreach測試:
a.代碼部分:
public static void Test_For(string[] inits) {
int length = inits.Length;
string txtfor="";
for (int i = 0; i < length; i++) {
//執行內容
txtfor += inits[i];
}
}
public static void Test_Foreach(string[] inits) {
string txt = "";
foreach (string s in inits) {
txt += s;
}
}
static void Main(string[] args)
{
string[] inits = new string[] { "1", "1", "1", "1", "1", "1", "1",
"1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1",
"1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1"};
Test.CodeTimer.Initialize();
Test.CodeTimer.Time("一般for循環:", 5, () => { Test_For(inits); });
Test.CodeTimer.Time("一般foreach循環:", 5, () => { Test_Foreach(inits); });
Test.CodeTimer.Time("並行for循環:", 5, () =>
{
Parallel.For(0, inits.Length, (i) =>
{
Test_For(inits);
});
});
Test.CodeTimer.Time("並行foreach循環:", 5, () =>
{
Parallel.ForEach(inits, (i) =>
{
Test_Foreach(inits);
});
});
Console.Read();
Console.ReadLine();
}
在測試代碼計數時間最早使用系統的stopWatch來完成,但考慮到系統的其他程序佔用資源,以及該程序的優先級別設置,數據統計等等。最終選擇採用老趙設計的CodeTimer來兩者之間的比較,當然我們也考慮現有的cpu都是多核多線程,所以我還加入了並行循環的比較, 在計算時間上我做了小改動:watch.ElapsedMilliseconds.ToString("N0")
+ "ms" 改爲 watch.Elapsed,更精確。
這是結果如下:
我們從上述可以得出,在單線程執行foreach會比for佔用cpu之原來得大,但在執行效率上有很大的提升。在並行執行中,foreach佔盡了各個優勢。
那麼我們在所有的執行循環體中是不是都把for改成foreach來執行呢? 回答:肯定不是。接下來我們說說哪些情況下使用的for而不是foreach:
1.在片段執行過程使用for,原因是foreach是逐個遍歷,至始至終都是從第0位置開始遍歷。
2.對循環執行的對象需要更改時使用for,原因foreach遍歷過程對象是隻讀狀態,不允許更改對象值。
3.循環的對象不是數組,列表對象使用for,原因foreach只能是集合對象遍歷。
總結:選擇使用哪個循環語法時,事先考慮是否存在集合對象,對象是否需要遍歷,以及代碼如何更加簡練。
打個自己剛開發的網站廣告:生活信息查詢平臺
轉載請標明原文地址,請大家支持版權。