【问题标题】:Error 'Iterator cannot contain return statement ' when calling a method that returns using a yield调用使用产量返回的方法时出现错误“迭代器不能包含返回语句”
【发布时间】:2014-06-16 22:51:55
【问题描述】:

我希望有一种更好的方法来编写此方法和重载,同时减少代码重复。我想返回列表中项目之间的一系列增量。这个方法:-

    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 语句返回一个值,或 yield break 结束迭代。”

我看过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;
            }
        }
    }

任何人都可以提出更好的方法吗?

【问题讨论】:

    标签: c# refactoring extension-methods ienumerable yield


    【解决方案1】:

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

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

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

    【讨论】:

    • IEnmuable 上的错字除外 :)
    【解决方案2】:

    单个方法不能同时使用yield returnreturn。您必须选择其中之一。

    您可以选择foreachyield return 列表:

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

    或者将你的代码分成两种方法:

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

    【讨论】:

    • 感谢蒂姆的回复。我真的希望你的第一个方法可以工作,但它不能编译:ErrorCannot 隐式转换类型 'System.Collections.Generic.IEnumerable' 到 'decimal'
    • @Dave00Galloway 哦,yield return 之后我做错了。试试item(我刚刚编辑了我的答案)
    • S - 谢谢,效果很好。我更喜欢这个 yield return item; 而不是 Jon Skeet 的回答,因为它避免了编写额外的方法,所以你只是从他那里偷了“答案”!
    • 这也有效,因为原始方法是扩展:- foreach (var item in sequence.CalculateDeltas()) yield return item;
    猜你喜欢
    • 2012-12-07
    • 1970-01-01
    • 1970-01-01
    • 2017-05-07
    • 2016-03-14
    • 1970-01-01
    • 2021-12-26
    • 2016-11-12
    • 2013-11-26
    相关资源
    最近更新 更多