Подтвердить что ты не робот

Закройте все открытые формы, кроме главного меню в С#

Попытка закрыть все формы, кроме основного меню, используя

FormCollection formsList = Application.OpenForms;

с циклом foreach и говорящим,

if (thisForm.Name != "Menu") thisForm.Close();

Что работает нормально, он пропускает меню и закрывает первый, но затем ошибки:

Коллекция была изменена; операция перечисления может не выполняться

и останавливается. Я пробовал несколько мест, и все они говорят, что этот цикл foreach - это способ сделать это, и это особенно раздражает, поскольку я не обновляю список своих форм после закрытия форм, которые, как я думал, могут работать. Единственное, о чем я мог подумать, это начать с обратной стороны и работать вперед, используя некоторое время.

4b9b3361

Ответ 1

Если вы используете foreach для перечисления через коллекцию, он не может быть изменен (элементы добавлены или удалены) во время итерации. Попробуйте скопировать ссылки на формы в другую коллекцию, а затем удалить их путем повторения этой коллекции.

В таких ситуациях вы можете использовать список или простой массив, например:

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();
}

Или вы можете использовать цикл for:

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

Или, мой новый и текущий любимый, вы можете использовать метод Reverse():

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

Ответ 2

Это происходит, когда коллекция изменяется внутри цикла foreach, который ее использует. Вы удаляете элемент из formsList внутри цикла.

Попробуйте следующее:

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

Ответ 3

Здесь еще более сжатый метод, который использует то же количество строк, что и ваш оригинальный метод:

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

Используя метод расширения Linq Cast, вы можете избежать цикла в коллекции для создания массива.

Ответ 4

Закрыть все формы:

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

Ответ 5

Как заявляет ошибка, вы не можете изменять коллекцию в своем foreach.

Вместо этого вы можете использовать обратный цикл for.

Ответ 6

поскольку коллекция форм обновляется для каждой итерации. Когда вы закрываете форму, она удаляется из коллекции формы. это как удаление объекта из памяти во время его использования.

Ответ 7

Коллекция была изменена; операция перечисления не может выполняться.

FormCollection formsList = Application.OpenForms;
            //for (int i = 0; i < formsList.Count; i++)
            foreach(Form  f in formsList )
            {
                if (f.Name != "Form1" || f.Name != "Home" || f.Name != "AdminHome")
                    f.Close();
            }
            this.Close();

Ответ 8

Я знаю, что это старо, но мне нужно было выполнить этот же сценарий и придумал элегантный и простой способ добиться этого, как показано ниже.

        Form[] formsList = Application.OpenForms.Cast<Form>().Where(x => x.Name == "Form1").ToArray();
        foreach (Form openForm in formsList)
        {                
            openForm.Close();
        }

Это закроет ВСЕ окна, которые открываются с помощью Form1