C#中有可扩展队列吗?

时间:2010-12-04 12:47:19

标签: c# .net loops queue

我有一组ID,我可以在其上执行一些操作:

Queue<string> queue = new Queue<string>();
queue.Enqueue("1");
queue.Enqueue("2");
...
queue.Enqueue("10");

foreach (string id in queue)
{
    DoSomeWork(id);
}

static void DoSomeWork(string id)
{
   // Do some work and oooo there are new ids which should also be processed :)
   foreach(string newID in newIDs)
   {
       if(!queue.Contains(newID)) queue.Enqueue(newID);
   }
}

是否可以向queue中的DoSomeWork()添加一些新项目,这些项目也将在主要的foreach-Loop中处理?

3 个答案:

答案 0 :(得分:3)

您正在做的是在更改集合上使用迭代器。这是不好的做法,因为一些集合在执行此操作时会抛出异常(例如,在枚举期间集合不应更改)。

使用以下方法,它也会使用新项目:

while (queue.Count > 0)
{
    DoSomeWork(queue.Dequeue());
}

答案 1 :(得分:1)

使用Dequeue而不是foreach循环。每当基础容器发生变化时,大多数枚举器都会失效。 En- / Dequeue是队列中的自然操作。否则,您可以使用List<T>HashSet<T>

while(queue.Count>0)
{
  var value=queue.Dequeue();
  ...
}

要检查项目是否已被处理,HashSet<T>是一个快速解决方案。在这些情况下,我通常使用HashSet和Queue的组合。这个解决方案的优点是它是O(n),因为检查和添加HashSet是O(1)。您的原始代码为O(n ^ 2),因为Contains上的Queue为O(n)。

Queue<string> queue=new Queue<string>();
HashSet<string> allItems=new HashSet<string>();

void Add(string item)
{
  if(allItems.Add(item))
    queue.Enqueue(item);
}

void DoWork()
{
    while(queue.Count>0)
    {
      var value=queue.Dequeue();
      ...
    }  
}

答案 2 :(得分:0)

循环迭代通常会添加更多工作;只是将队列作为参数传递给方法,添加到它应该可以正常工作。

问题是你应该使用Dequeue:

while(queue.Count>0) {
    DoSomeWork(queue.Dequeue());
}