【问题标题】:why a function which has yield return in it cannot be recursive?为什么一个有yield return的函数不能递归?
【发布时间】:2013-04-28 05:07:33
【问题描述】:

我有一段这样的代码

class Program
{
    static IEnumerable<string> GetSequences(string a)
    {
        yield return a;
        GetSequences(a + ">");
    }

    static void Main(string[] args)
    {
        foreach (var n in GetSequences(">"))
            Console.Write(n + ",");
    }
}

我期待这样的输出

,>>,>>>

但事实并非如此。它只打印“>”。有谁知道我错过了什么?

【问题讨论】:

  • 你只是返回传递的内容,即 ">"
  • 很明显,带有yield return 的函数可以是递归的:您已经在递归调用它。您忽略它的结果这一事实并没有减少它的递归性。

标签: c# recursion yield-return


【解决方案1】:

在函数本身中使用相同的 foreach:

static IEnumerable<string> GetSequences(string a)
{
    yield return a;
    foreach (var n in GetSequences(a + ">"))
        yield return n;
}

别忘了退出递归。

【讨论】:

    【解决方案2】:

    foreach 循环仅适用于 yield return,您在 GetSequences() 方法中的 GetSequences() 命令上没有 yield return;它返回的任何东西都不会被存储或返回。就像您正在这样做: 就像你在这样做:

    static IEnumerable<string> GetSequences(string a)
    {
        GetSequences(a + ">");
    }
    

    当然没有 return 语句(它不会编译,但你知道这一点)。 在玩了一会儿之后,如果您想使用递归,我建议您不要使用可枚举,特别是因为循环和递归旨在服务于不同的目的,而带有 IEnumerable 的 foreach 最适合具有已经列举了。上面建议的循环,按原样,只是启用无限递归,并像这样实现递归的转义:

        static IEnumerable<string> GetSequences(string a)
        {
            if(a.Length > 100)
                yield return a;
            else
                foreach (var n in GetSequences(a + ">"))
                    yield return n;            
        }
    

    产生以下输出: &gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;,(也许按比例计算,我不想数) 通过像这样实现它,我能够得到你想要的输出:

        static string GetSequences(string a, int len)
        {
            if (a.Length < len)
            {
                 return GetSequences(a + ">", len);
            }
            else
                return a;
        }
    
        static void Main(string[] args)
        {
    
            for (int i = 1; i < 5; i++)
            {
                Console.Write(GetSequences(">", i) + ",");
            }
            Console.Read();
        }
    

    当然,我的整数是任意的,它适用于任何长度。

    编辑:我知道有一种方法可以按照 abatishchev 所说的方式进行,但我想不通。绞尽脑汁后,我得到了以下结果:

        static IEnumerable<string> GetSequences(string a)
        {
            if (a.Length < 100)
            {
                yield return a;
                foreach (var n in GetSequences(a + ">"))
                    yield return n;
            }else
                yield break;
        }
    

    这有你想要的输出,虽然我仍然认为使用循环递归有点有趣。

    【讨论】:

      猜你喜欢
      • 2014-01-18
      • 2018-07-13
      • 2012-03-26
      • 2020-05-30
      • 2020-08-02
      • 2018-04-05
      • 2017-01-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多