Close all open forms except the main menu in C#

If you use foreach to enumerate through a collection, it can't be modified (items added or removed) during the iteration. Try copying references to the forms to another collection, and then remove them by iterating through that collection.

In situations like this, you can use a list or a simple array, such as:

List<Form> openForms = new List<Form>();

foreach (Form f in Application.OpenForms)
    openForms.Add(f);

foreach (Form f in openForms)
{
    if (f.Name != "Menu")
        f.Close();
}

Or you can use a for loop:

for (int i = Application.OpenForms.Count - 1; i >= 0; i--)
{
    if (Application.OpenForms[i].Name != "Menu")
        Application.OpenForms[i].Close();
}

Or, my new and current favorite, you can use the Reverse() method:

foreach (Form f in Application.OpenForms.Reverse())
{
    if (f.Name != "Menu")
        f.Close();
}

That happens when the collection is changed inside a foreach loop that uses it. You are removing an item from formsList inside the loop.

Try this:

for (int i = formsList.Count-1; i > 0; i--)
{
    if (formsList[i].Name != "Menu")
    {
        formsList[i].Close();
    }
}

Here's an even more concise method that uses the same number of lines as your original method:

Form[] forms = Application.OpenForms.Cast<Form>().ToArray();
foreach (Form thisForm in forms)
{
    if (thisForm.Name != "Menu") thisForm.Close();
}

By using Linq's extension method Cast, you can avoid looping through the collection to build an array.

Tags:

C#

Winforms