C# 递归在C语言中的工作原理#

C# 递归在C语言中的工作原理#,c#,recursion,C#,Recursion,这是我的密码 using System; public class Program { public static void Method(int flowerInVase) { if (flowerInVase > 0) { Method(flowerInVase - 1); Console.WriteLine(flowerInVase); } }

这是我的密码

using System;
public class Program
{
   public static void Method(int flowerInVase)
      {
         if (flowerInVase > 0)
         {
             Method(flowerInVase - 1);
             Console.WriteLine(flowerInVase);
         }
      }

   public static void Main()
   {
      Method(3);
   }
}
我对line
Console.WriteLine(flowerInVase)感兴趣方法调用自身,直到它被条件终止。只有在堆栈满后,它才会从上面弹出每个方法,控制台写入从至少1,2,3开始的数字

为什么
console.writeline
只有在堆栈弹出时才工作,为什么它不在方法到达终止时写入数字,比如3,2,1?编译器仅在完成递归时才使用writeline

编译器仅在完成递归时才使用writeline

它这么做是因为你让它这么做。在代码中,首先执行递归(调用
Method()
),只有当递归完成后,您才能写入数字

如果要在执行递归之前先写入数字,则需要切换代码中的语句:

public static void Method(int flowerInVase)
{
   if (flowerInVase > 0)
   {
       Console.WriteLine(flowerInVase);
       Method(flowerInVase - 1);
   }
}

调用的结构如下所示。也许这个可视化将帮助您理解为什么数字打印1、2、3而不是3、2、1:

Method(3);
  flowerInVase > 0 ?
  Yes - Method(2);
    flowerInVase > 0 ?
    Yes - Method(1);
      flowerInVase > 0 ?
      Yes - Method(0);
        flowerInVase > 0 ?
        No
      WriteLine(1);
    WriteLine(2);
  WriteLine(3);

原因是对
方法(flowerInVase-1)
的调用在对
WriteLine(flowerInVase)
的调用之前。执行跳转到方法的另一个副本,然后它才有机会打印它所在的数字。

如果您逐行跟踪代码执行,这是有意义的。如果你把它分解,它真正的意思是,在你有机会向控制台写任何东西之前,你总是要创建一个递归调用的新实例。只有创建了所有允许调用的调用(if语句失败)后,线程的控制才会返回到 现有的方法

Create method -> check parameter 
  -> create method - > check parameter
    -> create method -> check parameter
      etc. etc.
    -> print value
  -> print value
-> print value
现在,您看到它正在按调用的方式返回控制。最后一个调用的函数需要先完成其操作,然后调用它的函数才能完成操作。

因为它会这样做:

flowerInVase = 3
call Method(3)
    call Method(2)
        call Method(1)
        WriteLine(1)
    WriteLine(2)
WriteLine(3)
然后输出为:

1
2
3
如果您将行反转:

    Console.WriteLine(flowerInVase);
    Method(flowerInVase - 1);
它将首先打印,然后递归,因此它将打印3、2、1

为什么console.writeline只有在卡住的情况下才工作,为什么它没有 在方法到达终止点的过程中写入数字,如 3,2,1


因为你的
方法(flowerInVase-1)

也许您应该研究递归的含义。这是递归方法的一个非常简单的示例:即,一个调用自身的方法。递归在很多领域都有很多用途,特别是在编程方面,但这不是你要问的,也不是我要回答的

如果您逐行阅读代码,您将看到调用了
方法(3)
,这反过来调用
方法(2)
,最重要的是,它在输出值3之前进行此调用。因此,
方法(2)
将在输出方法(3)
的最后一行之前全部执行。同样,
方法(2)
在输出2之前调用自身,因此整个
方法(1)
将在此之前执行

一个简单的流程图:

Main() -> Method(3)               
              --->calls Method(2)
                            --->calls Method(1)
                                          -Method(0) not viable
                                          -if statement failed
                                          -Outputs '1'
                            -Outputs '2'
              -Outputs '3'
End of Main()

因为
if
语句中的行是按顺序排列的,所以得到的是1,2,3

Main()
调用
方法(3)

方法(3)
在打印“3”之前调用
方法(2)
。执行立即跳到
方法的顶部
;使用
flowersinvase=3
方法的第一次调用在递归调用完成之前不会完成。同样地,
方法(2)
立即调用
方法(1)
方法(1)
调用
方法(0)

方法(0)
不执行任何操作,并返回到方法(1)
,即它停止的位置;下一行是您的
WriteLine
调用,它打印“1”,然后返回,它在它停止的地方拾取对
方法(2)
的调用,打印“2”,以此类推为“3”


如果您调用的方法在跳转到它们递归调用的任何方法之前运行到完成状态,那么您只会得到“3,2,1”,这不是C#的工作方式。关于方法调用,您必须记住的是,一旦您调用了一个方法,执行将立即跳到您调用的方法的开头;方法调用后的代码将不会执行,直到方法返回。

可能的重复出于价值考虑,此网站上的人不会试图挑剔你。只是这个问题的格式不太适合这个网站。没有卡住,它叫做堆栈:)它被关闭了,所以我无法重新打开它,只需使用调试器逐步调试;我认为WriteLine在方法体中,所以应该一起完成,然后转到下一个方法如果您使用Visual Studio,您可以按F11(默认键绑定)调用的方式跳过每一行。您将看到,当执行时,点击对
方法的调用(flowerInVase-1)它立即再次跳到方法的顶部-但作为堆栈上的新方法。调用堆栈显示将反映这一点。谢谢。是的,我做到了。但经过你们的解释,伙计们,我有一个线索,我看到了什么,而按下F11。我看到它在所有递归完成后跳转到writeline,我只是不知道为什么,因为正如我之前所说的,我认为它应该完成整个方法,然后才调用返回方法(1)中的一个,就在它停止的地方-这个短语打破了僵局)谢谢