返回foreach中的第一个元素

时间:2011-07-20 13:03:23

标签: c# .net collections foreach

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

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

怎么做?

修改

@dlev + enumerator.Reset()

评论中的解决方案

9 个答案:

答案 0 :(得分:15)

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

Restart:
foreach(var item in things)
{
    DoSomething(item);
    if(WeShouldStartOver()) goto Restart;
}

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

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

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

这种情况要长得多,控制流程更复杂,并且仅使用数据标志来控制流程,而不是在程序的业务领域中表达含义。我认为所有这些都和“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;
}

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

答案 1 :(得分:10)

改为使用for循环。或者一会儿循环。

答案 2 :(得分:5)

不要认为有什么东西在建,但是怎么样......

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

编辑:优化

答案 3 :(得分:1)

据我所知,你真的不能这样做。

只需使用不同的循环,例如while,您可以在其中控制迭代器并决定是否增加或减少迭代器等。

答案 4 :(得分:1)

for(int i = 0;i<YourCollection.Count ; i++)
{
    if(YouNeedToStartOver)
    {
        i=-1;
        continue;
    }
}

答案 5 :(得分:0)

foreach范围内,您只能使用continue转到下一个元素,或者完全退出循环。您需要直接使用迭代器。

答案 6 :(得分:0)

你可以做点什么

   private static void LoopMethod()
        {
           i= 0;
            foreach (string str in jack)
            {
                if (i == 4)
                    LoopMethod();

                Console.WriteLine(str);
                i++;
            }
        }

答案 7 :(得分:-3)

如果我是你,我会考虑创建和使用该集合的枚举器。

    using (IEnumerator<T> enumerator = collection.GetEnumerator())
    {

        while (enumerator.MoveNext())
        {
            if (SatisfyResetCondition(enumerator.Current))                          
                enumerator.Reset();
            Console.WriteLine(enumerator.Current);
        }
    }

答案 8 :(得分:-3)

你不能在集合上使用foreach循环,因为当你使用foreach循环时,你无法访问正在使用的枚举器(它被编译器隐藏 - 这是foreach循环的全部要点!),并且集合不一定有一个索引器可以直接访问元素。

即使你可以,IEnumerator.Reset的接口契约也指定你根本不需要实现Reset,而是可以抛出异常。这意味着,对于所有集合,您无法保证Enumerator.Reset会将您返回到集合的开头。

所以不,你不能做你在问题中提出的问题;这是不可能的。