Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to break first foreach loop from second nested foreach loop in c# [duplicate]

Tags:

c#

how to break first for each loop from second nested for each loop in c#,I want to check some conditions in the second for each loop then try to break the parent for each loop

foreach(//do some stuff)
{
     foreach(//do some stuff)
     {
          if(//check some condition)
          {
                break;//but want to break first foreach loop
          }
     }
}
like image 862
Amit Kundu Avatar asked Mar 02 '16 12:03

Amit Kundu


Video Answer


1 Answers

Quick answer:

foreach(//do some stuff)
{
     foreach(//do some stuff)
     {
          if(//check some condition)
          {
                goto end; // I'd probably add a comment here
          }
     }
     // *1
}
end:
{} // the rest of your code.

But, but SESE...

SESE violations are violations of the Single Entry Single Exit principle. It's quite easy to fix, by using an extra condition:

bool found = false;
for (int i=0; i<foo.Count && !found; ++i)
{
    for (int j=0; j<bar.Count; ++j) 
    {
        if (...) { found = true; }
    }
    // *1 
    if (!found) { ... }
}

So why use a GOTO here?

I believe that creating proper, maintainable code means that you use the language constructs that most closely describes your intent. "Code" here is always composed of two things:

  • Control flow, which is expressed through things like for, while, break and goto.
  • Data flow, which is expressed through expressions, variables, and other memory access.

The intent of the OP is to break out of a nested loop, which is the equivalent of a control flow operation. I therefore believe you should use the control flow operation that most closely represents what the intent is - which is in this case a goto.

Note that this is not at all a reason you should abuse for introducing goto statements all over the place; if you do, the code will become very hard to read, which has nothing to do with maintainability and readability. You should consider the goto statement as a 'last resort control flow' statement, which is very rarely used in properly crafted code.

That said, in this case, this means that you shouldn't create local variables to handle control flow, unless that's absolutely necessary (e.g. if there's no language construct available that can express your intent clearly). For the same reason, I wouldn't have used Linq in this particular scenario.

I want performance. What should I do?

I believe most abuse of language constructs results from not understanding how the compiler deals with code, which is why I make it a habit of explaining parts of how it works internally. Please keep in mind that I recommend using a goto because it most clearly describes your intent, not because it might be a bit faster. Here goes:

Imagine being the compiler. You have a ton of code at the point of *1 in your code and cannot use return. Now there's two options:

  1. You can use a goto.
  2. You can use the extra flag.

Option 1 will compile to a field, which has memory. Memory is 'scarse' in the sense that compilers will do their best to consume as little memory as possible, preferable in registers. That's where your performance originates from. So, the compiler will attempt to eliminate the flag.

To do this, your compiler will do a ton of flow analysis and other stuff, in an attempt to determine that there are actually two code paths: the one is when the flag is set and the other one if it's not.

Now, if you're lucky the compiler will have its 'aha' moment and change your code from (2) to a simple GOTO, in which case the sky is still blue and everyone is happy.

However, if you're not lucky (and there are a ton of practical reasons for this to happen), it will not detect this from flow analysis and won't create the GOTO. Since your flag is used in the inner loop, it might even allocate a register for this, which might be the worst case scenario.

If you would have used the goto in the first place, there's no need for all this. You simply give the compiler the right solution. Simple.

Hrm do you have more details about how the compiler does this?

Yes, look at this 2 hour video of Chandler that explains a lot on how compilers work: https://www.youtube.com/watch?v=FnGCDLhaxKU

-updated- Apparently some people misintepreted my story as was pointed out by @Groo. I've made some adjustments to clarify what I meant to say.

like image 178
atlaste Avatar answered Oct 23 '22 12:10

atlaste