Reputation: 247
What is the best way to terminate all nested loops in the example below. Once the if statement is true, I want to terminate the outer for statement (with I). In the other words I need the whole loop to stop. Is there better way than setting I to 10?
for (int I = 0; I < 10; I++)
{
for (int A = 0; A < 10; A++)
{
for (int B = 0; B < 10; B++)
{
if (something)
break;
}
}
}
Upvotes: 14
Views: 2884
Reputation: 1086
Don't shoot me, but this might actually warrant a goto:
for (int I = 0; I < 10; I++) {
for (int A = 0; A < 10; A++) {
for (int B = 0; B < 10; B++) {
if (something)
goto endOfTheLine;
}
}
}
endOfTheLine:
Console.WriteLine("Pure evilness executed");
Upvotes: 15
Reputation: 881173
Assuming you want to exit from all loops, you can refactor it into something a little more structured:
bool done = false;
for (int i = 0; i < 10 && !done; i++) {
for (int a = 0; a < 10 && !done; a++) {
for (int b = 0; b < 10 && !done; b++) {
if (something) {
done = true;
continue;
}
}
}
}
Upvotes: 14
Reputation: 57974
I don't know if C#
supports it but some languages support:
break n;
Where n
is the number of nested loops to break.
Upvotes: 2
Reputation: 36438
simple solution is to refactor the nested loops into a separate method with the relevant return type being whatever you wanted to know at that point:
in my case I will assume you wanted the the values of I, A and B at that point, trivial with a Tuple instead.
// original method
...
var x = FindFirst()
...
// separate method
public Tuple<int,int,int> FindFirst()
{
for (int I = 0; I < 10; I++)
{
for (int A = 0; A < 10; A++)
{
for (int B = 0; B < 10; B++)
{
if (something)
return Tuple.Create(I,A,B);
}
}
}
return null;
}
If you need to pass in any additional state to the method (for the bounds, or the something bit) just pass them as parameters.
If you wanted to handle failing to find the first one in a different fashion then something like
bool TryFindFirst(out Tuple<int,int,int> x)
would be an alternate.
As a side note using capital letters for variable names (especially single letter ones) is considered poor style in c# (and many other languages)
Upvotes: 2
Reputation: 659984
If the loop bodies do not produce a side effect but rather merely are looking for the first value where "something" is true then would fix the problem by eliminating all the loops in the first place.
var query = from I in Enumerable.Range(0, 10)
from A in Enumerable.Range(0, 10)
from B in Enumerable.Range(0, 10)
where something(I, A, B)
select new { I, A, B };
var result = query.FirstOrDefault();
if (result == null)
{
Console.WriteLine("no result");
}
else
{
Console.WriteLine("The first result matching the predicate was {0} {1} {2},
result.I, result.A, result.B);
}
But don't do this if the loops have side effects; queries are a really bad place to put side effects. If the inner loop has a side effect then you can do something like this:
var triples = from I in Enumerable.Range(0, 10)
from A in Enumerable.Range(0, 10)
from B in Enumerable.Range(0, 10)
select new { I, A, B };
foreach(var triple in triples)
{
if (something(triple.I, triple.A, triple.B))
break;
DoSomeSideEffect(triple.I, triple.A, triple.B);
}
and now there is only one loop to break out of, not three.
Upvotes: 10
Reputation: 4152
for (int I = 0; I < 10; I++) {
for (int A = 0; A < 10; A++) {
for (int B = 0; B < 10; B++) {
if (something){
B=13;
A=13;
I=13;
}
}
}
}
A very primitive solution.
Upvotes: 2
Reputation: 1582
Personally I would go with Paxdiablo's method above (+1 for that), but an alternative is below - it depends if the OP needs to know what the I, A and B numbers are when "something" is true, be because iab were declared in the loop I'm guessing not.
bool done = false;
int i, a, b;
for (i = 0; i < 10 ; i++) {
for (a = 0; a < 10 ; a++) {
for (b = 0; b < 10 ; b++) {
if (something) {
done = true;
break;
}
}
if (done) break;
}
if (done) break;
}
// i, a and B are set to the last numbers where "something" was true
Upvotes: 1
Reputation: 43064
You could always exploit the fact that there is a conditional statement in the for
thus:
bool working = true;
for (int i=0; i<10 && working; i++)
{
for (int j=0; j<10 && working; j++)
{
for (int k=0; k<10 && working; k++)
{
Console.WriteLine(String.Format("i={0}, j={1}, k={2}", i,j,k));
if (i==5 && j==5 && k==5)
{
working = false;
}
}
}
}
Upvotes: 3
Reputation: 1466
If this is the final task in method then you can return when condition is true. otherwise you have to make all the values to max values
if (something)
{
I=10;
B=10;
A=10;
break;
}
Upvotes: 2
Reputation: 5566
the other possibility is to cascade the check on isSomething in all for loops. you add the
if (something)
break;
in all 3 loops
Upvotes: 1
Reputation: 13246
I would lean in favour of goto
also else you are going to have to exit each loop:
for (int I = 0; I < 10; I++)
{
for (int A = 0; A < 10; A++)
{
for (int B = 0; B < 10; B++)
{
if (something)
break;
}
if (something)
break;
}
if (something)
break;
}
Upvotes: 2
Reputation: 50825
Why not do:
for (int I = 0; I < 10 || !something; I++)
{
for (int A = 0; A < 10 || !something; A++)
{
for (int B = 0; B < 10; B++)
{
if (something)
{
I=10;
break;
}
}
}
}
Upvotes: 3
Reputation: 2112
You could always meet the loops expectations:
if (something) B = 10
Edit: (Appears you included this in your post through an edit)
If you don't like the way it looks, you could wrap a function such as:
Satisfy(B,10)
Then it looks cleaner, but really not needed.
Upvotes: 1
Reputation: 1062580
I would refactor this to a method, and just call return
whenever I need to.
You could also use goto
, and I have used goto
for this, but it gets frowned upon. Which is dumb; this scenario is why it exists in the language.
void DoSomeStuff()
{
for (int I = 0; I < 10; I++)
{
for (int A = 0; A < 10; A++)
{
for (int B = 0; B < 10; B++)
{
if (something)
return;
}
}
}
}
...somewhere else...
DoSomeStuff();
Upvotes: 32