我有一组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中处理?
答案 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());
}