分享
 
 
 

遍历ArrayList易犯错误

王朝other·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

遍历ArrayList易犯错误

场景:

将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 | 无名

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有