在C#中创建消费foreach

时间:2015-11-11 12:37:58

标签: c# .net

有没有办法在C#中创建消耗foreach循环? 基本上循环收集项目并同时使用它们?

用简单的英语:不要只是循环遍历元素,从集合中删除项目,用它做一些事情,然后转到下一个。

编辑我忽略了提到我正在使用生产消费模式,这就是为什么我想要一个消费的foreach。这里的大多数答案对于我在编辑之前描述的简单案例完全有效,尽管我的答案中描述了我想要的内容

5 个答案:

答案 0 :(得分:4)

使用Stack(后进先出)或Queue(先进先出)。

一个很好的例子是this "recursive" queue,它列出了目录中的所有文件。

答案 1 :(得分:2)

foreach中使用的集合是不可变的。这是由设计完成的。

MSDN说:

foreach语句用于遍历集合以获取所需的信息,但不能用于添加或删除源集合中的项目以避免不可预测的副作用。如果您需要在源集合中添加或删除项目,请使用for循环。

更新0.0: 可以使用for循环来编辑集合:   要将项添加到集合,可以使用for循环:

List<string> coll = new List<string>() { "1", "2", "3", "4", "5" };
for (int i = coll.Count-1; i>=0 ; i--)
{ 
   /* You can assign value to an item:
    coll[i] = "";       
   You can add an item to the collection:
   coll.Add(i.ToString());*/
   coll.RemoveAt(i);
   //or coll.Remove("your string value to delete");
}

答案 2 :(得分:2)

正如您对问题的评论所指出的,使用堆栈或队列是&#34;进程然后删除&#34;的最佳选择。图案。如果由于某种原因您不想使用这些专门的类,您可以使用普通List执行以下操作:

var items = new List<Item>() {item1, item2, item3};
while(items.Count > 0)
{
    ProcessItem(item[0]);
    items.RemoveAt(0);
}

但是你不能做的是修改foreach循环中的集合,如StepUp的回答中所述。

答案 3 :(得分:1)

如StepUp的回答所述,foreach循环中使用的集合是不可变的。但是可以使用BlockingCollection并使用GetConsumingEnumerable执行类似的操作,这会消耗Collection项目,同时迭代它们。鉴于我的收藏是并发产品消费计划的一部分(我在我的问题中忽略了),这更适合我。在更简单的情况下,虽然其他答案,使用堆栈或队列更合适,或简单的循环将从集合的末尾循环,直到开始并在途中删除项目(从开始到结束循环删除将跳过项目或以IndexOutOfBounds Exception

结束

答案 4 :(得分:1)

不完全是一个消费的前瞻&#34;但可能你正在寻找的是TPL DataFlow。

例如,请参阅:https://leanpub.com/tpldataflowbyexample/readMSDN: Create a DataFlow PipelineMSDN: Implement a Producer / Consumer Scenario

一个非常基本的例子可能如下所示:

  var actionBlock = new ActionBlock<int>(n => Console.WriteLine(n));

             for (int i = 0; i < 10; i++) {
                 actionBlock.Post(i);
             }

             Console.WriteLine("Done");

您还可以链接多个块以使用分叉等创建更复杂的消费策略。您还可以为步骤定义不同的调度程序类型。

对于非常简单的场景,这可能是超大的,但是TPL是一个非常好的扩展解决方案,可以让您对数据流的外观进行大量控制。