zoukankan      html  css  js  c++  java
  • 这段代码居然运行正常

     

    乍一看还以为这个世界变得太快自己不认识了,再一琢磨,原来是凑巧而已,世界虽然变了点,但基本的东西还是没变的。

                  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循环是从一开始的时候就把初始与终止条件定好了,在循环过程中其终止条件的值是不变的(不知道如何把DelphiCPU视图里的ASM代码拷出来,截个图算了)

    看最底部的两句dec esijnz -$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#里的这么复杂,所以它的编译器作了点优化。PSDelphi的虽然比较的简洁一点,但有时也太不方便,比如无法控制步长)。你删尽管删好了,反正它的i只到当时test.Count那个地方就停了。所以上面的代码可以运行。

     

    至于运行正常那正好是凑巧而已了。每次RemoveAt掉一个使ArrayList后部的元素都上提的同时而i又增1,由此每次RemoveAtfor循环遍历漏掉一个元素的情况下,正好那个漏掉的元素本身是不符合条件的,反正漏掉它也无关痛痒。所以上面的运行结果看起来很正常。其实把

                   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);

    一切恢复正常,速度也飞快。

     

     

  • 相关阅读:
    vue-打包文件解析
    vue-动态路由
    vue-代码跳转路由
    vue-<routerl-link>属性补充
    vue-默认路由重定向和路由模式的切换
    vue-配置路由规则和显示路由
    路由器实验之Serial接口的静态路由配置
    交换机实验之交换机基本配置、交换机端口的基本配置、管理MAC地址表
    数据库表结构(字段信息等)导出Word,Excel,HTML,CHM等格式
    《数据库系统概论》学习总结——附件四(数据库实验(ADO.NET实现数据库操作))
  • 原文地址:https://www.cnblogs.com/lichdr/p/87184.html
Copyright © 2011-2022 走看看