程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> Effective C#原則11:選擇foreach循環(1)

Effective C#原則11:選擇foreach循環(1)

編輯:關於C語言

C#的foreach語句是從do,while,或者for循環語句變化而來的,它相對要好 一些,它可以為你的任何集合產生最好的迭代代碼。它的定義依懶於.Net框架裡 的集合接口,並且編譯器會為實際的集合生成最好的代碼。當你在集合上做迭代 時,可用使用foreach來取代其它的循環結構。檢查下面的三個循環:

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

對於 當前的C#編譯器(版本1.1或者更高)而言,循環1是最好的。起碼它的輸入要少些 ,這會使你的個人開發效率提提升。(1.0的C#編譯器對循環1而言要慢很多,所 以對於那個版本循環2是最好的。) 循環3,大多數C或者C++程序員會認為它是最 有效的,但它是最糟糕的。因為在循環外部取出了變量Length的值,從而阻礙了 JIT編譯器將邊界檢測從循環中移出。

C#代碼是安全的托管代碼裡運行的 。環境裡的每一塊內存,包括數據的索引,都是被監視的。稍微展開一下,循環 3的代碼實際很像這樣的:

// Loop 3, as generated by compiler:
int len = foo.Length;
for ( int index = 0; index < len; index++ )
{
 if ( index < foo.Length )
  Console.WriteLine( foo[index].ToString( ));
 else
   throw new IndexOutOfRangeException( );
}

C#的JIT編譯 器跟你不一樣,它試圖幫你這樣做了。你本想把Length屬性提出到循環外面,卻 使得編譯做了更多的事情,從而也降低了速度。CLR要保證的內容之一就是:你 不能寫出讓變量訪問不屬於它自己內存的代碼。在訪問每一個實際的集合時,運 行時確保對每個集合的邊界(不是len變量)做了檢測。你把一個邊界檢測分成了 兩個。

你還是要為循環的每一次迭代做數組做索引檢測,而且是兩次。 循環1和循環2要快一些的原因是因為,C#的JIT編譯器可以驗證數組的邊界來確 保安全。任何循環變量不是數據的長度時,邊界檢測就會在每一次迭代中發生。 (譯注:這裡幾次說到JIT編譯器,它是指將IL代碼編譯成本地代碼時的編譯器, 而不是指將C#代碼或者其它代碼編譯成IL代碼時的編譯器。其實我們可以用不安 全選項來迫使JIT不做這樣的檢測,從而使運行速度提高。)

原始的C#編 譯器之所以對foreach以及數組產生很慢的代碼,是因為涉及到了裝箱。裝箱會 在原則17中展開討論。數組是安全的類型,現在的foreach可以為數組生成與其 它集合不同的IL代碼。對於數組的這個版本,它不再使用IEnumerator接口,就 是這個接口須要裝箱與拆箱。

IEnumerator it = foo.GetEnumerator( );
while( it.MoveNext( ))
{
 int i = (int) it.Current; // box and unbox here.
 Console.WriteLine( i.ToString( ) );
}

取而代之的是,foreach語句為數組生 成了這樣的結構:

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

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved