Удаление элементов управления в цикле - PullRequest
5 голосов
/ 10 апреля 2009

Вчера я написал кусок кода, чтобы удалить все элементы управления в форме, которая соответствует определенным критериям. Наивно это пишу, вот что я придумаю.

for (int i = 0; i < this.Controls.Count; ++i)
{
    if (this.Controls[i].Name.Length == 2)
    {
        this.Controls.Remove(this.Controls[i);
    }
}

Но бывает так, что код неправильный. Затем я изменяю его на:

foreach (Control ctr in this.pbBoardImage.Controls)
{
    if (ctr.Length == 2)
    {
        this.Controls.Remove(ctr);
    }
}

Но это все еще не правильно. Я знаю, что правильный путь будет:

for (int i = this.Controls.Count - 1; i >= 0; i--)
{
    if (this.Controls[i].Name.Length == 2)
    {
        this.Controls.Remove(this.Controls[i]);
    }
}

Однако это все еще не выглядит элегантно. Я не мог использовать List.RemoveAll, так как this.Controls не был List. Так я могу попросить более элегантный способ, желательно без использования цикла?

1 Ответ

13 голосов
/ 10 апреля 2009

Не знаю, почему вам не понравился этот ответ ... Я выделил важное RemoveAt; однако в качестве альтернативы в .NET 3.5 / C # 3.0: LINQ:

        var qry = from Control control in Controls
                  where control.Name.Length == 2
                  select control;

        foreach(var control in qry.ToList()) {
            Controls.Remove(control);
        }

(оригинал)

Вы не можете Remove в пределах foreach - это ломает итератор. Общий подход здесь состоит в том, чтобы перебрать в обратном направлении :

for (int i = this.Controls.Count - 1; i >= 0; i--) {
    if (this.Controls[i].Name.Length == 2) {
        this.Controls.RemoveAt(i); // <=========== *** RemoveAt
    }
}

Это позволяет избежать проблем "выключено одним" и т. Д.

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