在调用使用yield返回的方法时,错误'Iterator不能包含return语句'

时间:2014-04-30 14:40:17

标签: c# refactoring extension-methods ienumerable yield

我希望有更好的方法来编写这种方法&代码重复较少的重载。我想在列表中的项之间返回一系列增量。这种方法: -

    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;
        }
    }

工作正常。

然后我考虑了一个允许绝对增量的重载,但是如果不需要绝对值则调用原始方法: -

    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);
        }
    }

但由于错误

而无法编译
  

“无法从迭代器返回值。使用yield return   声明返回一个值,或者产生中断以结束迭代。“

我看过this post,似乎除了重复原始方法中的代码之外,我将无法做任何其他事情: -

    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;
            }
        }
    }

有人能建议更好的方法吗?

2 个答案:

答案 0 :(得分:16)

单一方法不能yield returnreturn。你必须选择其中一个。

您可以在列表中foreachyield return

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

或者将您的代码分为两种方法:

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

答案 1 :(得分:4)

最简单的方法可能是将方法拆分为两个,其中一个是通过迭代器块实现的,其中一个不是:

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;
    }
}

这种分割方法还允许您热切地验证sequence,例如

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

...在非迭代器块方法中。