Evil 域

当Evil遇上先知

导航

关于foreach的一个小局限

Posted on 2007-07-27 08:58  Saar  阅读(597)  评论(7编辑  收藏  举报
    foreach是C#相对于C/C++在程序循环结构的实现中引入的一个新的关键词,其作用是遍历一个集合中的每一个元素。
    例如,我们有一个DropDownList类型的下拉框ddlItems,把遍历它的每一项,我们可以写如下代码:
            string temp="";
            
for (int i = 0; i < ddlItems.Items.Count; i++)
            {
                temp 
+= ddlItems.Items[i].Text;
            }

    这里,需要借用一个循环变量i。在C#中,这样的循环可以利用foreach来实现,而不需要借助循环变量:
            string temp="";
            
foreach (ListItem li in ddlItems.Items)
            {
                temp 
+= li.Text;
            }

    呵呵,这样写,虽然是没了i,却多了一个ListItem的对象引用。但这样写的好处也是显而易见的,程序员不必担心漏了或者循环变量越界问题。所以,一直很喜欢用foreach,直到有一天,我写了如下代码:
            foreach (ListItem li in ddlItems.Items)
            {
                
if (li.Text == "Delete Me") ddlItems.Items.Remove(li);
            }

    这段代码想要把ddlItems的列表里的项的Text属性为"Delete Me"的项删掉,结果,系统在编译时通过,在运行时,却抛出了异常。原来,使用foreach的时候,要求全集不能有变化。因为删掉了符合条件的li,所以,导致ddlItems.Items发生了变化,致使foreach抛出异常。解决方法也很简单,回到原始的方式上来,把代码改成以下形式,就OK了:
            for (int i = ddlItems.Items.Count; i >= 0; i--)
            {
                
if (ddlItems.Items[i].Text == "Delete Me") ddlItems.Items.RemoveAt(i);
            }

    这里要注意的,i的值必须是从最大往最小递减,因为在删除一个项后,如果这个项不是最后一个,那么,其后面的项的index都会减1,这样,递增时计算就会出错。