вставка в очередь при ее перечислении

Я хочу выполнить поиск по дереву в ширину, используя очередь

var q = new Queue<T>();

q.Enqueue(Root);

foreach(T root in q)
{
  foreach(T t in root.Children)
    q.Enqueue(t);
}

Однако я получаю сообщение «Коллекция была изменена после создания экземпляра перечислителя». Исключение.

Есть ли тип С#, с которым я могу это сделать?


Редактировать: небольшое чтение заставило меня подумать, что я могу делать это совершенно неправильно.

Есть ли способ использовать foreach для удаления из очереди?


это работает, но некрасиво (ОМХО)

var q = new Queue<T>();

q.Enqueue(Root);

while(q.Count > 0)
{
  T root = q.Dequeue();
  foreach(T t in root.Children)
    q.Enqueue(t);
}

person BCS    schedule 02.03.2009    source источник
comment
Что эффективно делает ваш рабочий пример? Если я что-то не упустил, вы просто постоянно добавляете, а затем удаляете элементы, в конечном итоге получая пустую очередь. Должна ли быть обработка после команды Dequeue?   -  person Andrew Shepherd    schedule 03.03.2009


Ответы (2)


Вы не можете перечислять IEnumerable и изменять один и тот же IEnumerable одновременно. Я не думаю, что существует коллекция С#, которая позволит это сделать.

person Jason Punyon    schedule 02.03.2009

Конструкция foreach здесь не работает.

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

var l = new List<T>();
l.Add(Root);
int i = 0;
while(i < l.Count)
{
    T root = l[i];
    foreach(T t in root.Children)    
    {
        l.Add(t);
    }
    ++i;
}


// And because you really wanted a queue
var q = new Queue<T>(l);
person Andrew Shepherd    schedule 02.03.2009