开发者

Return to first element in foreach

Say I move开发者_如何学运维 with foreach loop in some collection.

At some point (e.g. by 4th elem) I want to return to first element of this collection (to go through all the elements again)

How to do this?

EDIT

Solution in comment by @dlev + enumerator.Reset()


Though this solution is inelegant, and plenty of people will tell you that it exposes you to all manner of danger, you can always just do:

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

That is easy, clear and correct. (A lot of people will reflexively tell you that gotos are the spawn of evil and always wrong. Those people might be confusing "inelegant" and "easily abused" with "morally wrong".)

If you're one of those people who thinks that gotos are always wrong, you can hide the goto. Mysteriously, when you spell "goto" as "while" and "break" it is no longer morally wrong!

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

That is much longer, has way more complicated control flow, and uses a data flag just for control flow, rather than for expressing the meaning in the business domain of the program. I would argue that all of those things are as bad as the "goto", but some people really like this sort of thing.

I personally would be inclined to refactor the loop into a helper method:

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;
}

Can you explain why you want to do this strange thing? Maybe there is a better way to do what you want. Because frankly, all these solutions are pretty bad.


Use a for loop instead. Or a while loop.


Don't think there is anything build in but how about...

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

EDIT: Optimised


You can't really do that as far as I know.

Just use different loop, for example while where you can control the iterator and decide if you increase or descrease it etc.


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


Within a foreach you can only go to the next element with continue or step out of the loop completely. You would need to use the iterator directly.


you could do something of this sort

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

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


I would consider creating and using an Enumerator of the collection if I were you.

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

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


You can't do this with a foreach loop over a collection, because when you use a foreach loop, you cannot get access to the Enumerator being used (it's hidden by the compiler - which is the whole point of the foreach loop!), and a collection does not necessarily have an indexer for direct access to the elements.

Even if you could, the interface contract for IEnumerator.Reset specifies that you do not have to implement Reset at all and can throw an exception instead. This means you cannot guarantee, for all collections, that Enumerator.Reset will return you to the beginning of the collection.

So no, you can't do what you have asked in the question; it is impossible.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜