遍历ArrayList易犯错误

遍历ArrayList易犯错误遍历ArrayList易犯错误场景:将ArrayList中符合条件的记录删掉,第一时间写出的程序如下:            foreach (string aStr in  aList)            {                if (aStr.Equals(textBox1.Text))                {                    aList.Re

大家好,欢迎来到IT知识分享网。

场景:

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

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/21058.html

(0)

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

关注微信