返回foreach中的第一个元素

Sai*_*int 2 .net c# collections foreach

假设我在某些集合中使用foreach循环.

在某些时候(例如,到第4个元素)我想回到这个集合的第一个元素(再次遍历所有元素)

这该怎么做?

编辑

@dlev + enumerator.Reset()评论中的解决方案

Eri*_*ert 16

虽然这个解决方案不够优雅,但很多人会告诉你它会让你面临各种各样的危险,你可以随时做到:

Restart:
foreach(var item in things)
{
    DoSomething(item);
    if(WeShouldStartOver()) goto Restart;
}
Run Code Online (Sandbox Code Playgroud)

这很容易,清楚和正确.(很多人会反思性地告诉你,邪恶是邪恶的产物,而且总是错的.那些人可能会因为"道德错误"而混淆"不雅"和"容易被滥用".)

如果你是那些认为getos总是错误的人之一,你可以隐藏goto.神秘的是,当你将"goto"拼写为"while"和"break"时,它不再是道德错误!

bool loopTheLoop = true;
while(loopTheLoop)
{
    loopTheLoop = false;
    foreach(var item in things)
    {
        DoSomething(item);
        if(WeShouldStartOver())
        {
            loopTheLoop = true;
            break;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这种情况要长得多,控制流程更加复杂,并且只使用数据标志来控制流程,而不是在程序的业务领域中表达含义.我认为所有这些都和"goto"一样糟糕,但是有些人真的很喜欢这种东西.

我个人倾向于将循环重构为辅助方法:

while(LoopTheLoop()) {}
...
// Returns true if we bailed early, false if we did not.
bool LoopTheLoop()
{
    foreach(var item in things)
    {
        DoSomething(item);
        if(WeShouldStartOver()) return true;
    }
    return false;
}
Run Code Online (Sandbox Code Playgroud)

你能解释一下为什么要做这件奇怪的事吗?也许有更好的方法来做你想要的.坦率地说,所有这些解决方案都非常糟糕.

  • @hoodaticus:我对你的异议感到困惑,有两种方式.首先,如果OP有一个特殊条件 - 如果有一些线程问题,或者如果恐龙使用"goto"或其他东西会攻击他 - 那么由OP来告诉我们特殊情况.如果原始海报没有在问题中包含相关信息,那么SO上几百万个答案中的每一个都可能是"错误的".如果没有给出任何特殊条件,则可以合理地假设没有特殊条件. (4认同)
  • 关于你的断言"线程安全"序列在有一个未完成的枚举时锁定自己:你确定吗?这似乎是**疯狂危险的**模式.应该在尽可能短的时间内取出锁,但是在迭代器的创建和销毁之间可能会有任意多的时间.在获取锁定和释放锁定之间运行的所有代码都应该被充分理解,以确保锁定正确,但枚举通常会产生任意外部代码.你所描述的似乎非常不安全. (4认同)

dev*_*tal 10

请改用for循环.或者一会儿循环.

  • @Saint`foreach`无论如何编译成`while`循环:http://msdn.microsoft.com/en-us/library/aa664754%28v=vs.71%29.aspx (2认同)
  • @polishchuk:然后调用[`IEnumerator.Reset`](http://msdn.microsoft.com/en-us/library/system.collections.ienumerator.reset.aspx)(假设已实现`Reset`).很容易在`while`循环中执行此操作. (2认同)

mus*_*fan 5

不要认为有任何东西,但如何...

bool tryAgian = false;
do
{
   tryAgian = false;
   foreach(var item in items)
   {
      //do something
      if(needToStartAgain)
      {
         tryAgain = true;
         break;
      }
   }
} while(tryAgain)
Run Code Online (Sandbox Code Playgroud)

编辑:优化