iT邦幫忙

DAY 11
1

.NET程式效能Issue系列 第 11

[Day 11][C#]Effective C# 條款十一: 優先採用foreach迴圈

  • 分享至 

  • xImage
  •  

C#中的foreach迴圈並不僅僅是do…while或是for迴圈的變形。它會與.NET框架中的集合接口做緊密的結合,在編譯時為我們最佳化程式碼。除此之外foreach使用上也具備較高的相容性。

讓我們先來看三種迴圈的寫法:

int[] foo = new int[100];
foreach(int i in foo)
    Console.WriteLine(i.ToString());
int[] foo = new int[100];
for(int index=0;index<foo.Length;index++)
    Console.WriteLine(foo[index].ToString());
int[] foo = new int[100];
int len = foo.Length;
for(int index=0;index<len;index++)
    Console.WriteLine(foo[index].ToString());

第一個迴圈的寫法,在.NET1.1以後的版本,其效率最佳,程式碼也最少。而第三個迴圈寫法是最慢的,因為會阻礙JIT編譯器移除迴圈內的範圍檢查,讓JIT編譯器編譯成下面這樣:

int[] foo = new int[100];
int len = foo.Length;
for(int index=0;index<len;index++){
    if(index<foo.Length)
        Console.WriteLine(foo[index].ToString());
    else
        throw new IndexOutOfRangeException();
}

在.NET 1.0以前,使用foreach效率上會較差,因為JIT編譯器會把程式編譯成下面這樣:

IEnumerator it = foo.GetEnumerator();
while(it.MoveNext())
{
   int i = (int) it.Current;
   Console.WriteLine(i.ToString());
}

這樣的程式會產生裝箱與拆箱,因此在效能上會有不良的影響。但在.NET 1.1以後的版本,JIT編譯器會把程式編譯成下面這樣:

int[] foo = new int[100];
for(int index=0;index<foo.Length;index++)
    Console.WriteLine(foo[index].ToString());

所以我們可以得知,使用foreach來處理迴圈,編譯器會幫我們自動產生最佳的程式碼。

除效能外,foreach迴圈在使用上也具備較高的相容性。不論巡覽的陣列其上下限是多少,foreach迴圈總是能正確的運行。在多維陣列上,不論陣列維度維多少,使用foreach迴圈都能幫我們巡覽所有陣列元素。就算本來使用的是陣列,後來因需求變更為使用集合類別,使用foreach迴圈不需做任何的修改。


上一篇
[Day 10][C#]Effective C# 條款十: 理解GetHashCode()方法的缺陷
系列文
.NET程式效能Issue11
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
TOM
iT邦新手 5 級 ‧ 2024-02-05 09:26:05

很棒@@沒有注意的細節

我要留言

立即登入留言