我在用foreach的时候遇到过这样的问题:
我在一个WINFORM中加了个菜单,菜单的下拉列表里除了有ToolStripMenuItem,还有分隔线(ToolStripSeparator)
具体代码如下:
            foreach (ToolStripMenuItem item0 in MainMenuStrip.Items)
            {
                foreach (ToolStripMenuItem item1 in item0.DropDownItems)
                {
                    MessageBox.Show(item1.Text); //在迭代到ToolStripSeparator时会出错
                }
            }
我看了一下它们的继承关系,ToolStripSeparator派生于ToolStripItem,而 ToolStripMenuItem 派生于ToolStripDropDownItem,而ToolStripDropDownItem 派生于 ToolStripItem
,简单点说,ToolStripSeparator 和ToolStripMenuItem 都是派生于ToolStripItem
而item0.DropDownItems 就是一个ToolStripItemCollection(ToolStripItem的集合)
难道说 foreach (ToolStripMenuItem item1 in item0.DropDownItems)这里迭代的是item0.DropDownItems的数量
或者说foreach 里面迭代的次数是in 后面的集合里(DropDownItems)的数量,而不是集合(DropDownItems)中ToolStripMenuItem 的数量????????
这个让我觉得很奇怪,是微软故意设置成这样的还是有什么特别的原因,请高手告诉我.

解决方案 »

  1.   

    就是说,在一个派生于同一个基类的不同子类集合中,用其中一个子类进行迭代时,为什么是用集合的总数量进行迭代而不是用集合中具体子类的数量来迭代
    foreach (ToolStripMenuItem item1 in item0.DropDownItems) 
    这句用的是DropDownItems的数量进行的迭代,而不是DropDownItems中ToolStripMenuItem 的数量进行迭代的
      

  2.   

    foreach (ToolStripMenuItem item0 in MainMenuStrip.Items)
    {
          foreach (ToolStripMenuItem item1 in item0.DropDownItems)
          {
               MessageBox.Show(item1.Text); //在迭代到ToolStripSeparator时会出错
          }
    }item0 是在 MainMenuStrip.Items 其中。
    item1 是在 item0.DropDownItems 其中。
      

  3.   

    if (item0 is ToolStripDropDownItem)
    {
                    foreach (ToolStripMenuItem item1 in item0.DropDownItems) 
                    { 
                        MessageBox.Show(item1.Text); //在迭代到ToolStripSeparator时会出错 
                    } 
    }
      

  4.   

    就是,在迭代一个同时拥有派生于同一个基类的不同子类集合时,迭代的次数为什么是集合的总数量而不是集合中迭代的子类的数量
    foreach (ToolStripMenuItem item1 in item0.DropDownItems) 中迭代的是item0.DropDownItems的数量,而不是item0.DropDownItems
    中ToolStripMenuItem 的数量,为什么MS要这样做,还有就是,我要只迭代ToolStripMenuItem 的话,除了在foreach中做判断还能有什么好方法!
      

  5.   

    ... ToolStripSeparator 和ToolStripMenuItem 都是派生于ToolStripItem ...
    Yes, but ToolStripSeparator is NOT a ToolStripMenuItem.
      

  6.   


    是的,错误原因,我知道,我只是想深究一下foreach的具体工作原理,或者说,MS为什么要这样
    在迭代一个同时拥有派生于同一个基类的不同子类集合时,迭代的次数为什么是集合的总数量而不是集合中迭代的子类的数量
    foreach (ToolStripMenuItem item1 in item0.DropDownItems) 中迭代的是item0.DropDownItems的数量,而不是item0.DropDownItems
    中ToolStripMenuItem 的数量
      

  7.   

    我觉得这似乎不是什么问题啊。就象For循环一样,首先,in 前面的部分是一个临时变量,而in后面的部分才是循环要处理的主体,当然要以in后面的为准。在本例中,item0.DropDownItems本身是一个集合,我们的Foreach要循环处理集合中的内容,那么,当然要依次处理集合中的每个元素,而这每一个元素,当然就是item0.DropDownItems指定的DropDownItems集合。这个说法有点儿绕,我这么说吧,你可以按照范型来理解,Foreach处理的本身,是将后面的集合按Object类型取出来,再赋给前面的临时变量(当然同时会涉及类型转换)。在这个取值的过程中,虽然前面我们定义了变量类型,但取出的时候,是不确定类型的,所以,原始类型是什么,就是什么,如果不能转换为目标类型,就会报错。换个角度来说,这种问题,应该用计算机处理的思路来想,而不是人的思维模式去考虑。计算机只知道集合和集合中的元素的概念,所以,不会从语义上去考虑你想要干什么地。
      

  8.   

    也就是说,可以肯定的是,在foreach中是直接遍历in后面集合中所有的元素,而in前面定义的临时变量只是用来强制转换的,而集合中有元素不能转换就会报错.
    嗯,这样的话,foreach中也是要遍历in后面集合中所有的元素,那它是怎么能达到比for()语句效率更高的呢,我看过的一些书或者文章好像都是说的foreach要比for()的效率要高些,如果不是也请说说它们的差别
      

  9.   

    就是说,在一个派生于同一个基类的不同子类集合中,用其中一个子类进行迭代时,为什么是用集合的总数量进行迭代而不是用集合中具体子类的数量来迭代 
    foreach (ToolStripMenuItem item1 in item0.DropDownItems) 
    这句用的是DropDownItems的数量进行的迭代,而不是DropDownItems中ToolStripMenuItem 的数量进行迭代的