Закройте все открытые формы, кроме главного меню в C # - PullRequest
13 голосов
/ 27 января 2012

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

FormCollection formsList = Application.OpenForms;

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

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

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

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

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

Ответы [ 8 ]

55 голосов
/ 27 января 2012

Если вы используете 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 голосов
/ 26 ноября 2016

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

        for (int i = Application.OpenForms.Count - 1; i >= 0; i--)
        {
            if (Application.OpenForms[i].Name != "Menu")
                Application.OpenForms[i].Close();
        }
2 голосов
/ 27 января 2012

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

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

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

2 голосов
/ 27 января 2012

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

Попробуйте это:

for (int i = formsList.Count-1; i > 0; i--)
{
    if (formsList[i].Name != "Menu")
    {
        formsList[i].Close();
    }
}
0 голосов
/ 09 июня 2017

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

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

Это закроет ВСЕ окна, которые были открыты, с именем Form1

0 голосов
/ 15 ноября 2013

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

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();
0 голосов
/ 27 января 2012

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

0 голосов
/ 27 января 2012

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...