程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> c# 中的 for vs foreach

c# 中的 for vs foreach

編輯:C#入門知識

c# 中的 for vs foreach



今天偶然與建議不要用for,可讀性太差性能又低,可我個人認為要根據具體情況而定,畢竟for在大部分語言的關鍵字,可讀性不可能因為一個關鍵字的替代而變好,多數取決於設計和編碼習慣。
至於性能,打算寫段代碼對它們分別測試一下。
var arr = Enumerable.Range(0, 100000000).ToList();
	
	var sw = Stopwatch.StartNew();
	for(var i = 0;i < arr.Count; i++){}
	sw.Stop();
	Console.WriteLine("for loop takes : " + sw.ElapsedTicks);
	
	sw = Stopwatch.StartNew();
	foreach(var x in arr){}
	sw.Stop();
	Console.WriteLine("for loop takes : " + sw.ElapsedTicks);




先看生成的IL


for循環的部分:
...
IL_0018:  ldc.i4.0    
IL_0019:  stloc.2     // i
IL_001A:  br.s        IL_0022
IL_001C:  nop         
IL_001D:  nop         
IL_001E:  ldloc.2     // i
IL_001F:  ldc.i4.1    
IL_0020:  add         
IL_0021:  stloc.2     // i
IL_0022:  ldloc.2     // i
IL_0023:  ldloc.0     // arr
IL_0024:  callvirt    System.Collections.Generic.List.get_Count
IL_0029:  clt         
IL_002B:  stloc.s     04 // CS$4$0000
IL_002D:  ldloc.s     04 // CS$4$0000
IL_002F:  brtrue.s    IL_001C


...




除了IL_0024中的callvirt會觸發方法虛表查詢外,幾乎不存在任何高消耗的指令。再來看foreach的IL部分:


...
IL_005A:  ldloc.0     // arr
IL_005B:  callvirt    System.Collections.Generic.List.GetEnumerator
IL_0060:  stloc.s     05 // CS$5$0001
IL_0062:  br.s        IL_006E
IL_0064:  ldloca.s    05 // CS$5$0001
IL_0066:  call        System.Collections.Generic.List+Enumerator.get_Current
IL_006B:  stloc.3     // x
IL_006C:  nop         
IL_006D:  nop         
IL_006E:  ldloca.s    05 // CS$5$0001
IL_0070:  call        System.Collections.Generic.List+Enumerator.MoveNext
IL_0075:  stloc.s     04 // CS$4$0000
IL_0077:  ldloc.s     04 // CS$4$0000
IL_0079:  brtrue.s    IL_0064
IL_007B:  leave.s     IL_008C
IL_007D:  ldloca.s    05 // CS$5$0001
IL_007F:  constrained. System.Collections.Generic.List<>.Enumerator
IL_0085:  callvirt    System.IDisposable.Dispose
IL_008A:  nop         
IL_008B:  endfinally  
IL_008C:  nop   
...




首先可以看到很多方法調用,並且在循環體內部每次都要調用方法MoveNext。最後可以看到,有end finally,意味著這個循環外部包了一層try-finally。從IL來看,foreach要比for慢的多了。


現在來看StopWatch的執行結果。

for loop takes : 764538
for loop takes : 1311252




for幾乎快了一倍。


結論:編程語言提供的關鍵字是為了解決某種問題而存在,需要對具體的業務場景進行判斷再決定,有關性能方面,一定要拿出數據說話。

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