场景:

将ArrayList中符合条件的记录删掉,第一时间写出的程序如下:

foreach (string aStr in  aList)
            {
                if (aStr.Equals(textBox1.Text))
                {
                    aList.Remove(aStr);
                }
            }
似乎没有错误,编译也通过的,但运行时如果真的遇到符合条件的数据,则会抛出错误:


简单的解决办法是如何呢?这时用Clone方法最好不过了,用如下代码:

ArrayList bList = (ArrayList)aList.Clone();
            foreach (string aStr in  bList)
            {
                if (aStr.Equals(textBox1.Text))
                {
                    aList.Remove(aStr);
                }
            }

似乎集合类型都会有这样的问题的。

posted on 2004-09-08 13:53 风前絮~~ 阅读(1047) 评论(25)  编辑 收藏

评论
# re: 遍历ArrayList易犯错误    
用for就可以避免这样的问题,而且for的执行效率还高过foreach 
2004-09-08 14:10 | 什么都不知道 
# re: 遍历ArrayList易犯错误    
啊,你.....你居然...居然敢用foreach来reomove,这是臭名昭著的Collection问题..... 
2004-09-08 14:24 | 寒枫天伤 
# re: 遍历ArrayList易犯错误    
我一般是用 
foreach(object item in al.ToArray()) 
.. 
或者是 in new ArrayList(somecollection).

2004-09-08 14:55 | Lostinet 
# re: 遍历ArrayList易犯错误    
好象是有一个浅表拷贝的方法。 
最好是用哪个,不要用Clone 
2004-09-08 15:11 | hyifeng 
# re: 遍历ArrayList易犯错误    
用for语句反向遍历即可 
2004-09-08 16:07 | feilng 
# re: 遍历ArrayList易犯错误    
我也犯过这样的错误,呵呵 
2004-09-08 16:10 | cure 
# re: 遍历ArrayList易犯错误    
To 什么都不知道:
for的方法也可以啊,代码如下?
            for (int i=0;i<aList.Count;i++)
                if (aList[i].Equals(textBox1.Text))
                    aList.RemoveAt(i);

To Lostinet :
你的方法也不错啊

To hyifeng:
对于ArrayList,Clone已经是一个浅表副本了。你说的是MemberwiseClone吗?

看来这种处理已经有三种方法了,foreach里面用Clone,for循环,ToArray,不知道那种比较好呢?
如何可以获得比较的数据?

2004-09-08 16:12 | 风前絮~~ 
# re: 遍历ArrayList易犯错误    
To feilng:

反向遍历?有什么好处啊?大致如何实现呢? 
2004-09-08 16:18 | 风前絮~~ 
# re: 遍历ArrayList易犯错误    
我也有过,for应该是最安全的,而且简单易懂

Clone和ToArray至少增加了处理量 
2004-09-08 16:23 | dali 
# re: 遍历ArrayList易犯错误    
To 风前絮~~ : 
对于for的代码,应该增加一个条件分支,调用了RemoveAt方法的话,index不能够增加。也就是说循环递增语句不应该写在for的括号里面。 
2004-09-08 17:56 | FantasySoft 
# re: 遍历ArrayList易犯错误    
受不了你们了,竟然。。。。竟然这种低级的错误都犯!!!!一个还不要紧,竟然是一群!!!晕~

删除的代码如下:

for (int i=aList.Count; --i >=0;)
    if (aList[i].Equals(textBox1.Text))
        aList.RemoveAt(i);
2004-09-08 18:54 | 老翅 
# re: 遍历ArrayList易犯错误    
呵呵~ 
2004-09-08 19:20 | hBifTs 
# re: 遍历ArrayList易犯错误    
To 老翅:

哈哈~~ 话也不能这么说了,编程那里会没有错误呢?要不也不会有BUG了。

感谢你贴的代码,我试过了,没有问题,可以说是for的一种方法。

To FantasySoft :

我那个for的代码也是通过了的,可以达到效果,请指明我代码错误,感谢! 
2004-09-08 19:58 | 风前絮~~ 
# re: 遍历ArrayList易犯错误    
To 风前絮~~ :代码本身语法没有错,只是逻辑上有问题而已。因为RemoveAt方法会改变Count方法的返回值,就造成了不是每个元素都被遍历到。这也是feilng和老翅提出反向遍历的原因。 
请看以下代码: 
using System.Collections; 
using System; 
class Test 

public static void Main() 

ArrayList test = new ArrayList(); 
for(int i=0; i < 3; i++) 
test.Add("test"); 
test.Add("testAgain"); 
test.Add("testAgain"); 
for(int i=0; i < test.Count; i++) 

if (test[i].Equals("test")) 
test.RemoveAt(i); 

for(int i = 0; i < test.Count;i++) 
Console.WriteLine(test[i]); 

}

test这个ArrayList里面的"test"是不是应该都被remove掉呢?事实上如果这样写,还是会剩下一个的。 
2004-09-09 02:22 | FantasySoft 
# re: 遍历ArrayList易犯错误    
To FantasySoft:

十分感谢! 原来的代码因为每个不相同的,因此没有发现这个问题。 
仔细想了下,确实如你所说: Count变了,使得index=0的被漏掉了。

看来for的方法只有反向遍历了。

有空用ILDASM看了下三种不同方法生成的代码,比较对应函数,发现用的堆栈最大值一样,代码长度不同,for的最短,ToArray()居中,Clone最多。
 
正向for的方法要加个语句就可以了,但看起来比反向臃肿了:
            for (int i=0;i<aList.Count;i++)
                if (aList[i].Equals(textBox1.Text))
                {
                    aList.RemoveAt(i);
                    i--;
                }
2004-09-09 09:18 | 风前絮~~ 
# re: 遍历ArrayList易犯错误    
To 风前絮~~ :可以这样写      
for (int i=0;i<aList.Count;) 
      if (aList[i].Equals(textBox1.Text)) 
      { 
             aList.RemoveAt(i); 
      } 
      else 
              i++; 
这样写是不是就更清晰了呢?for的递增语句不一定要写到for的括号里面的。

2004-09-09 10:24 | Fantasysoft 
# re: 遍历ArrayList易犯错误    
对呀,也是个方法! ^_^ 
2004-09-09 10:36 | 风前絮~~ 
# re: 遍历ArrayList易犯错误    
恕我直言,看到楼主你的“仔细想了下,确实如你所说:Count变了,使得index=0的被漏掉了。”这句话,感觉你并没有真正理解为什么会产生楼顶的问题

被遗漏的并不是原list的0号item,而是1号item

为什么呢?因为当你remove第i个item时,第[i + 1, count)域中所有items的索引值皆减一(Array是连续的,要满足只要有k ∈ [0, count)则Array[k]必存在),那么当你在循环下一轮用i + 1为索引访问的即是原先list中索引为i + 2的那个item,由此可知,上例中0号被删除时,原1号变为新0号,原2号变为新1号。。。下一轮访问的1号就是先前的2号,而原始的1号则永远没有被访问到

明白了这个自然可以得出正确的迭代方法,正序时需注意索引和可能变化的终止条件,倒序时则简单些 
2004-09-09 14:44 | 问题男 
# re: 遍历ArrayList易犯错误    
To 问题男:

Oh~~ Sorry,估计是我的表达有问题。 
index=0是Count变了后的,它原来的index确实=1,正如你所说的。

感谢指正! 
2004-09-09 15:16 | 风前絮~~ 
# re: 遍历ArrayList易犯错误    
re: 遍历ArrayList易犯错误 
用for语句反向遍历即可 
2004-09-08 16:07 | feilng

完全同意,我觉得这是最好的办法了 
p.s.这种事情,没有出过错的人第一次都会写错的,哈哈 
2004-09-09 16:56 | myrat 
# re: 遍历ArrayList易犯错误    
看看这段代码,会有什么结果?

int[] myarray = {1,2,3};

foreach(int num in myarray){ 
    num++; 

2004-09-09 17:21 | juqiang 
# re: 遍历ArrayList易犯错误    
To juqing:

有趣啊
应该是不行的

--------------------------------------------------------------------------------
MSDN中的说明:
foreach 语句为数组或对象集合中的每个元素重复一个嵌入语句组。foreach 语句用于循环访问集合以获取所需信息,但不应用于更改集合内容以避免产生不可预知的副作用。

--------------------------------------------------------------------------------

num++ 等价于 num = num + 1,修改内容了。
编译报错:
...(201): 无法分配到“num”,因为它是只读的

2004-09-09 17:33 | 风前絮~~ 
# 遍历ArrayList易犯错误[TrackBack]    
Ping Back来自:blog.csdn.net
windsails引用了该文章,地址: http://blog.csdn.net/windsails/archive/2004/09/10/100331.aspx 
2004-09-10 13:21 | windsails 
# re: 遍历ArrayList易犯错误    
为什么要反向?

int i =0; 
while( i<aList.Count) 

if (aList[i].Equals(textBox1.Text)) 

aList.RemoveAt(i) 
continue; 

i++; 
}

2004-10-20 21:29 | 大力水手 
# re: 遍历ArrayList易犯错误    
反向简单且效率高啊,aList.Count只在初始化时用一次,其他情况要每次都用啊。虽说aList.Count也是变量,但从机器码的角度来说,间接地址引用还是要花比寄存器引用多很多的时间的。 
2004-12-09 12:45 | 无名

遍历ArrayList易犯错误相关推荐

  1. java代码书写易犯错误

    java代码书写易犯错误: 常见报错: 控制台报错: 找不到或无法加载主类 HelloWorld 原因: java.lang.NoClassDefFoundError: cn/itcast/day01 ...

  2. OSDev——初学者易犯错误

    原文链接:https://wiki.osdev.org/Beginner_Mistakes 主页:https://blog.csdn.net/qq_37422196/article/details/1 ...

  3. Python初学者易犯错误集合

    Python初学者易犯错误集锦 注释与数据类型使用 分支判断/循环语句 函数定义与使用 模块导入与使用 类与对象 异常处理 与C/C++.Java等编译型语言相比,Python语言显得更简洁优雅,敲起 ...

  4. 研发各阶段易犯错误小结

    题记:以下是研发各阶段易出问题的小结,越小细节,越容易犯错误.需要多注意! 一.需求方面 1.需求文档 真正领会客户需求,形成指导开发人员的需求文档或者需求规格说明书是非常难的一件事情. 2.需求文档 ...

  5. 系统管理员易犯错误及解决方法汇总

    原文出自:http://os.51cto.com/art/201101/241510.htm 本文分享的都是系统管理员在工作的时候容易犯的错误,经抚琴煮酒整理并提供解决方法,希望可以给大家一些指导,避 ...

  6. Quartus II ( 18.1)使用时易犯错误(个人经验)

    上FPGA实验课时,需要用到Quartus II软件,犯了不少错误,主要是仿真时出错误,这里和大家分享下: 错误1: 这是由于仿真前,没有设置好仿真器的位置导致的:在 Tools->Option ...

  7. eclipse新手易犯错误, eclipse快捷键失效错误;

    太低级的错误了,对于eclipse开发人员来说,但对于新手确实很愁啊: 刚接触eclipse,打开一个项目后,查找方法实现等一些快捷键都失效了:连ctrl + s 都不管用了:网上查找可能是输入法修改 ...

  8. 十个 Linux 新手管理员易犯错误

    点击蓝字关注我们 如果您是Linux的新手,那么一些常见错误很可能会给您带来麻烦.提前了解它们,您就可以再逐渐熟悉Linux时避免出现重大问题. 1 从不同来源安装软件 Linux 发行版一般都会有默 ...

  9. 【C 语言】一级指针 易犯错误 模型 ( 判定指针合法性 | 数组越界 | 不断修改指针变量值 | 函数中将栈内存数组返回 | 函数间接赋值形参操作 | 指针取值与自增操作 )

    文章目录 一.判定指针合法性 二.数组越界 三.不断修改指针变量值 四.函数中将栈内存数组返回 五.函数间接赋值形参操作 六.指针取值与自增操作 一.判定指针合法性 判定指针合法性时 , 必须进行如下 ...

最新文章

  1. 微软私有云分享(R2)7-Linux虚拟机无DNS?
  2. 【数据结构与算法】之深入解析“买卖股票的最好时机II”的求解思路与算法示例
  3. C#+SQL Server数据库系统操作日志的实现完整案例
  4. 企业级应用,如何实现服务化一(项目架构演化)
  5. 再见,金庸;再见,江湖
  6. 准备好所有应用程序以进行本地化
  7. java中set语句_数据步骤中的多个SET / MERGE语句
  8. HibernateUtil类(可用于连接多个数据库)
  9. Swagger——与WebAPI整合
  10. 完全采用CSS的CROSS BROWSER TABBED PAGES
  11. [置顶]灰のNOIP总结
  12. Mac安装Mysql,并启动
  13. PTA 数据结构与算法 7-8 哈利·波特的考试
  14. 水星路器服务器无响应,水星路由器无法上网怎么办?
  15. 深入理解什么是Beta分布
  16. Python 豆瓣TOP250 电影爬取
  17. 理解v8的Isolate调度
  18. 物联网毕业设计题目大全
  19. webworker应用场景_JavaScript 工作原理之七-Web Workers 分类及 5 个使用场景
  20. 合宙模块LUA相关资料汇总

热门文章

  1. centos7 RPM命令安装操作
  2. 互联网晚报 | 2月21日 星期一 | 北京冬奥会闭幕;天猫将新增菜鸟驿站送货上门服务;上汽奥迪首款电动车型开启预售...
  3. 车联网创新生态发展报告
  4. 这一领域,互联网巨头纷纷入局!
  5. 2020年中国便利店发展报告
  6. html5 上传 原理,浅谈使用HTML5的FormData上传文件原理!!!
  7. 第四届大数据科学与工程国际会议(2019)
  8. 超级弹珠游戏(洛谷P2356题题解,Java语言描述)
  9. 【Java】《Java编程的逻辑》第3章 类的基础 笔记+感悟分享
  10. 驾校一点通下载|驾校一点通电脑版下载