这段代码居然运行正常
2005-01-06 09:52
274 查看
乍一看还以为这个世界变得太快自己不认识了,再一琢磨,原来是凑巧而已,世界虽然变了点,但基本的东西还是没变的。
ArrayList test = new ArrayList();
int i;
for(i = 0;i < 20;i++)
test.Add(i);
for (i = 0;i < test.Count;i++)
if (i % 2 != 0)
test.RemoveAt(i);
for(i = 0;i < test.Count;i++)
Console.WriteLine("Array [{0}] is {1}",i,test[i]);
Console.Read();
这种类型的代码在Delphi下别说是运行结果正常,根本就是连运行都运行不了的,最后肯定会报出来一个“List index out of bounds()”这样的错误。
首先是它运行不报错,说明For循环与在delphi下是不太一样的。
Delphi代码:
for i := 0 to test.Count - 1 do
if (i mod 2) <> 0 then
test.Delete(i);
它的for循环是从一开始的时候就把初始与终止条件定好了,在循环过程中其终止条件的值是不变的(不知道如何把Delphi的CPU视图里的ASM代码拷出来,截个图算了),
看最底部的两句dec esi、jnz -$20。在最开始进入循环的时候这个esi就定了。所以说在循环体内虽然有test.Delete(i)这样的语句,但其由test.Count – 1计算得的终止条件没有变,它在最开始的时候就已经把它取出来(当然它不是取终止条件,实际上是直接把循环次数算出来给了esi的,把循环初始条件改为非0开始能看得更明白点)。所以上面这种从头开始删的方法是会报错的。
而在C#里,上面那段代码查看IL有
IL_0036: callvirt instance int32 [mscorlib]System.Collections.ArrayList::get_Count()
IL_003b: blt.s IL_0024
类似的语句。这里的for循环在执行过程中其终止条件是一直在变化的(这里for的流程决定了其for循环的强大之处;Delphi里的那个for本身的语法没有C/C#里的这么复杂,所以它的编译器作了点优化。PS:Delphi的虽然比较的简洁一点,但有时也太不方便,比如无法控制步长)。你删尽管删好了,反正它的i只到当时test.Count那个地方就停了。所以上面的代码可以运行。
至于运行正常那正好是凑巧而已了。每次RemoveAt掉一个使ArrayList后部的元素都上提的同时而i又增1,由此每次RemoveAt后for循环遍历漏掉一个元素的情况下,正好那个漏掉的元素本身是不符合条件的,反正漏掉它也无关痛痒。所以上面的运行结果看起来很正常。其实把
if (i % 2 != 0)
改为
if (i % 3 != 0)
就可以看出结果不正常了,当然if (i % 3 == 0) 这样的条件出来结果也是正常的,也是因为漏掉的元素无关痛痒的缘故。
当然即使能运行正常也不要写上面那样的代码好,只有20个元素看不太出来,如果元素一多就严重影响性能了啦。
还好世界其实并没有变。只是一个for不同而已,删东西还是从尾部开始删。
for(i = test.Count - 1;i >=0;i--)
if (i % 3 != 0)
test.RemoveAt(i);
一切恢复正常,速度也飞快。
相关文章推荐
- 很奇怪,下面这段代码在VC6.0里面运行正常,但在VS2010面确有错误提示,求高手解释!
- extjs中的JS代码在firefox可以正常运行,在IE中无法运行的方法。
- 在运行程序时报错:"如果在 Code First 模式下使用,则使用 T4 模板为 Database First 和 Model First 开发生成的代码可能无法 正常运行。若要继续使用 Database First 或 Model First,请确保在执行应用程序的 config 文件中指 定 Entity Framework 连接字符串。若要将这些从 Database First 或 Mod
- gma950 调试 xna4.0代码 编译正常 运行出错
- VFP的代码混淆器,只在VFP9下运行正常
- 关于可运行代码无法正常执行的使用说明
- 调试经验 | Visual Studio中代码正常运行,但运行生成的exe报错“0xc000007b无法正常启动”
- extjs中的JS代码在firefox可以正常运行,在IE中无法运行的方法。
- SnmpTrap 线程 内附代码,eclipse可正常运行测试!
- 通过log4net写日志_代码正常运行,日志未写入
- Java代码查错----保持代码正常运行(一)
- AS项目运行正常,但查看代码飘红the file size exceeds configured limit.
- 有的时候 火狐 正常运行extjs代码而 google 却运行不了
- 编译链接正常,但是应用程序未运行到自己的代码就莫名奇妙崩溃!
- 加密后的php代码需要ZendGuardLoader模块才能正常运行
- Android Studio 中的类文件前标识图标显示为 j 而不是C,代码的左边没有了颜色显示,布局文件的引用也没有蓝色显示,代码大部分变成了白色。项目能正常编译运行,且敲代码时也没有了提示的问题
- 迈普-MP2600企业路由器简单配置可正常运行实例代码
- 在OD中修改代码可以正常运行,尝试各种补丁却不行
- IntelliJ IDEA编译环境编写JSP文件报错且没有代码提示,还能正常运行
- 关于可运行代码无法正常执行的使用说明