Закройте все открытые формы, кроме главного меню в С#
Попытка закрыть все формы, кроме основного меню, используя
FormCollection formsList = Application.OpenForms;
с циклом foreach и говорящим,
if (thisForm.Name != "Menu") thisForm.Close();
Что работает нормально, он пропускает меню и закрывает первый, но затем ошибки:
Коллекция была изменена; операция перечисления может не выполняться
и останавливается. Я пробовал несколько мест, и все они говорят, что этот цикл foreach - это способ сделать это, и это особенно раздражает, поскольку я не обновляю список своих форм после закрытия форм, которые, как я думал, могут работать. Единственное, о чем я мог подумать, это начать с обратной стороны и работать вперед, используя некоторое время.
Ответы
Ответ 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