对比C#中for和foreach循环的性能

开发 后端
在C#中有for和foreach循环,对于for循环大家还是比较了解,那么foreach循环呢?这里为大家比较一下二者的性能差别。

笔者在看了《Effective C#》了解到foreach循环,使用foreach循环语句,它会编译为不同的代码,自动将每一个操作数强制转换为正确的类型。

大家先来看看如下三个循环:

  1. int[] foo = new int[100];  
  2.  1,  foreach (int i in foo)  
  3. Console.WriteLine(i.ToString());  
  4. 2,for(int index=0;index                Console.WriteLine(foo[index].ToString());  
  5. 3,int len=foo.Length;  
  6. for(int index=0;index                Console.WriteLine(foo[index].ToString());  

这三个循环是我在看《Effective C#》中看到的,发现书中说第三个循环和如下代码等效,经过使用ILDasm.exe工具查看IL代码发现这个说法并不正确:

  1. int len=foo.Length;  
  2. for(int index=0;index   
  3. {  
  4.      if(index   
  5.           Console.WriteLine(foo[index].ToString());  
  6.       else 
  7.             throw new IndexOutOfRangeException();  

书中的看法是数组的边界测试会被执行两次(编译器生成的代码一次,JIT编译阶段还要执行一次检查),但是的确没有在IL代码中发现C#的编译器生成类似的逻辑,所以这个说法有问题!

一般C++转过来的程序员都很喜欢这样写循环,认为这样就不会每一次循环都计算一次Length属性的值了,可以带来性能上的提升!经查看IL代码,实际情况也就是如此!

但是,这样写会带来另外的问题,那就是破坏了JIT对代码的进行的优化,这样的写法在每一次循环中都要做数组的边界检查,这样也带来了性能上的损失,而且这个损失要比每次计算Length要大,如果我们按第二种写法,JIT只在第一次循环之前检查一次数组界限(JIT这种优化只针对f循环中访问一维0基数组,并且索引是0和Length之间的元素)

看来JIT不喜欢我们这样帮助他优化代码,这样反而破坏了JIT本身的优化!

我们再来看看第一种写法和第二种写法,通过查看IL代码,他们生成的代码比较类似,差别是使用foreach循环是把数组元素放到i变量里!

C#编译器对第一种写法(使用foreach循环)针对数组做了特殊的处理,并没有像其他集合那样在内部使用迭代器,这里如果使用迭代器的话会导致装箱和拆箱操作,这样会带来性能上的损失!看来C#编译器总是可以为foreach生成很高效率的代码,而且可以带来很多其他的好处,例如简化代码的编写,或是将来把foo变成其他集合 而foreach循环不必修改(使用for循环必须修改代码),操作数强制类型转换等.

【编辑推荐】

  1. C#字符ASCII码学习经验
  2. C#数值类型之间的转换概述
  3. 日期型数据转换成C#长整型数据
  4. C#查看Excel对象模型分析
  5. C#日期型数据简单剖析
责任编辑:彭凡 来源: 博客园
相关推荐

2009-07-31 18:39:31

C#中foreach引

2009-08-18 14:14:45

C#扩展方法性能测试

2022-08-27 14:42:45

Java集合数组

2020-10-16 08:30:00

foreach编程语言C#

2024-03-11 01:00:00

jsfor循环

2011-06-09 09:08:00

C#循环结构

2009-09-17 18:56:22

CLR Via C#

2009-06-19 09:36:27

C#执行速度IronPython

2015-04-01 14:34:37

C#dynamicDictionary性

2021-10-14 07:55:17

提示技巧C#

2024-03-19 14:41:08

C#操作符开发

2009-08-28 16:37:32

C# for循环

2024-04-18 09:16:03

EnumeratePythonFor循环

2014-03-27 11:34:09

C#优化性能优化

2021-11-30 00:12:43

C#多线程循环

2009-08-03 18:35:02

Boxing和UnboC#

2011-06-17 16:42:23

C#

2009-04-28 10:23:58

VB.NETC#对比

2017-02-22 14:09:31

Javaforeach反编译

2009-05-11 10:40:36

.NETLINQforeach
点赞
收藏

51CTO技术栈公众号