Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I use 'continue' and `break` in an extension method?

Tags:

c#

.net

morelinq

I have defined the following extension method:

public static void ForEach<T>(this IEnumerable<T> sequence, Action<T> action)
{
   foreach (T obj in sequence)
   { 
      action(obj); 
   } 
}

I can then use it as:

new [] {1, 2, 3} // an IEnumerable<T>
.ForEach(n => 
{
  // do something 
});

I want to be able to take advantage of continue and break inside my extension method so that I can do:

new [] {1, 2, 3}
.ForEach(n => 
{
    // this is an overly simplified example
    // the n==1 can be any conditional statement
    // I know in this case I could have just used .Where
    if(n == 1) { continue; }
    if(n == -1) { break; }      
    // do something 
});

Can these keywords only be used within a for, foreach, while or do-while loops?

like image 538
MaYaN Avatar asked Dec 20 '22 02:12

MaYaN


2 Answers

Can these keywords only be used within a for, foreach, while loops?

Yes. Those statements are limited to loop types. As the docs say:

The continue statement passes control to the next iteration of the enclosing while, do, for, or foreach statement in which it appears.

And:

The break statement terminates the closest enclosing loop or switch statement in which it appears. Control is passed to the statement that follows the terminated statement, if any.

I'd recommend you use a regular foreach, which is self expressive as is. I think any attempt to use them semantically inside your ForEach extension method will result in weirder code than using a regular loop.

I mean, is this not simpler?:

var arr = new [] {1, 2, 3}
foreach (int number in arr)
{
    if(n == 1) { continue; }      
    if(n == -1) { break; }      
}
like image 52
Yuval Itzchakov Avatar answered Jan 11 '23 17:01

Yuval Itzchakov


In addition to Yuval's answer I'd like to add that you could implement something like this as follows:

Change the Action<T> into a Func<T, bool> which takes a T parameter and returns a bool result.

The "continue" case could easily be handled by returning from the function upon the condition, thus continuing with the next iteration of the loop.

The "break" case could be handled by returning a bool from the function that indicates whether to continue or not:

public static void ForEach<T>(this IEnumerable<T> sequence, Func<T, bool> action)
{
  foreach (T obj in sequence)
  { 
    if (!action(obj)) 
      break;
  }
}

new [] {1, 2, 3}.ForEach(n => 
{
    if(n == 1) { return true;}      
    if(n == -1) { return false; }  

    // do something 
    ...
    return true;
});
like image 32
Thorsten Dittmar Avatar answered Jan 11 '23 17:01

Thorsten Dittmar