The error "Iterator cannot contain a return statement" when calling a method that returns using profitability

I hope there is a more convenient way to write this method and overload with less code duplication. I want to return a sequence of deltas between items in a list. this method: -

public static IEnumerable<decimal> CalculateDeltas(this IEnumerable<decimal> sequence) { decimal prev = default(decimal); foreach (var item in sequence) { var current = item; decimal diff = current - prev; prev = item; yield return diff; } } 

works great.

Then I thought of an overload that would allow an absolute delta, but would call the original method if an absolute is not required: -

  public static IEnumerable<decimal> CalculateDeltas(this IEnumerable<decimal> sequence,bool absolute) { if (absolute) { decimal prev = default(decimal); foreach (var item in sequence) { var current = item; decimal diff = Math.Abs(current - prev); prev = item; yield return diff; } } else { return CalculateDeltas(sequence); } } 

but this does not compile due to an error

"Cannot return value from iterator. Use return return to return value or exit interrupt to complete iteration."

I looked through this post , and it looks like I can’t do anything but repeat the code from the original method:

  public static IEnumerable<decimal> CalculateDeltas(this IEnumerable<decimal> sequence,bool absolute) { if (absolute) { decimal prev = default(decimal); foreach (var item in sequence) { var current = item; decimal diff = Math.Abs(current - prev); prev = item; yield return diff; } } else { decimal prev = default(decimal); foreach (var item in sequence) { var current = item; decimal diff = current - prev; prev = item; yield return diff; } } } 

Can anyone suggest a better way to do this?

+8
yield c # extension-methods ienumerable refactoring
source share
2 answers

One method cannot be both yield return and return . You must choose one or the other.

You can either do foreach before the yield return list:

 else { foreach (var item in CalculateDeltas(sequence)) yield return item; } 

Or split your code into two methods:

 if (absolute) return CalculateAbsoluteDeltas(sequence); else return CalculateDeltas(sequence); 
+11
source share

The simplest approach is probably to split the method into two, one of which is implemented through an iterator block, and one of which is not:

 public static IEnumerable<decimal> CalculateDeltas(this IEnumerable<decimal> sequence, bool absolute) { return absolute ? CalculateAbsoluteDeltas(sequence) : CalculateDeltas(sequence); } private static IEnumerable<decimal> CalculateAbsoluteDeltas (IEnumerable<decimal> sequence) { decimal prev = default(decimal); foreach (var item in sequence) { var current = item; decimal diff = Math.Abs(current - prev); prev = item; yield return diff; } } 

This separate approach also allows us to state the sequence with confidence, for example.

 if (sequence == null) { throw new ArgumentNullException("sequence"); } 

... in the non-iterative block method.

+4
source share

All Articles