Error 'Iterator cannot contain return statement ' when calling a method that returns using a yield

拟墨画扇 提交于 2019-12-08 14:58:05

问题


I'm hoping there's a nicer way to write this method & overloads 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 just fine.

I then thought about an overload which would allow an absolute delta, but would call the original method if absolute wasn't 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 doesn't compile because of Error

"Cannot return a value from an iterator. Use the yield return statement to return a value, or yield break to end the iteration."

I've had a look at this post and it seems like I won't be able to do anything other than repeating 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 of doing this?


回答1:


A single method cannot both yield return and return. You must choose one or the other.

You can either do a foreach to yield return the list:

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

Or separate your code into two methods:

if (absolute)
    return CalculateAbsoluteDeltas(sequence);
else
    return CalculateDeltas(sequence);



回答2:


The simplest approach is probably to split the method into two, one of which is implemented via an iterator block and one of which isn't:

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 split approach also allows you to eagerly validate sequence, e.g.

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

... in the non-iterator block method.



来源:https://stackoverflow.com/questions/23391119/error-iterator-cannot-contain-return-statement-when-calling-a-method-that-ret

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!