今天在百度知道看到這個一個問題:
【問題:】
點擊button1之后只有兩個按鈕消失,再點擊剩下兩個才能消失。按我寫的這個語句來說應該是一下子全部消失才對啊。求告訴哪出錯了!十分只是初步懸賞,如果解決了了會有追加!!下面是button1點擊事件的處理代碼。。。
private void button1_Click(object sender, EventArgs e) { foreach (Control c in this.panel1.Controls)
這是click事件的處理辦法
private void button1_Click(object sender, EventArgs e)
{
foreach (Control c in this.panel1.Controls)
{
c.Dispose();
}
}

【有網友有如下解答:】
我試了一下,是foreach遍歷的問題
似乎Control在Dispose的時候會把自己從父控件的Controls集合中移出。那么,根據迭代器的設計規范,在迭代過程中集合不應該被改變,如果迭代器檢查到集合被改變了應該拋出異常,但是這里沒有拋出異常。【注1】
結果就是異常迭代——foreach沒有遍歷集合中所有內容。你在c.Dispose()前面或后面加個MessageBox就可以看出來了,foreach只執行了兩次。
改成用for循環+索引方式訪問元素就可以了:
for(int i=panel1.Controls.Count -1;i>=0;i--)
{
Control c=panel1.Controls[i];
c.Dispose();
}
或者直接清空Controls集合,等垃圾回收執行析構函數:
panel1.Controls.Clear();
【注1】
看了下ControlCollection的MoveNext源碼,果然沒有檢查集合的改變:
public bool MoveNext()
{
if ((this.current < (this.controls.Count - 1)) && (this.current < (this.originalCount - 1)))
{
this.current++;
return true;
}
return false;
}
當你迭代完第二個元素后,this.controls.Count等於3-2=1,this.current=1,迭代就停止了。實際上集合中還有兩個元素。
【替代解決方案】
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace WindowsFormsApplication2
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
Queue<Control> query = new Queue<Control>();//臨時存儲獲取到的control控件
/// <summary>
/// 遞歸獲取panel1上的所有控件,並臨時存儲到一個隊列中
/// </summary>
/// <param name="item"></param>
void DS(Control item)
{
for (int i = 0; i < item.Controls.Count;i++ )
{
if (item.Controls[i].HasChildren)
{
DS(item.Controls[i]);
}
else
{
query.Enqueue(item.Controls[i]);
}
}
}
private void button1_Click(object sender, EventArgs e)
{
DS(panel1);
//刪除遍歷到的控件
while (query.Count != 0)
{
query.Dequeue().Dispose();
}
}
}
}