摘自:Effective_CSharp 改善C#程序的50种方法
使用foreach来取代其它的循环结构。检查下面的三个循环:
int [] foo = new int[100];
//
foreach (int i in foo)
Console.WriteLine(i.ToString());
//
for (int index = 0; index < foo.Length; index++)
Console.WriteLine(foo[index].ToString());
//
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的代码实际很像这样的:
//
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变量)做了检测。你把一个边界检测分成了两个。