递归是如何工作的

这是我的代码

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

我对行Console.WriteLine(flowerInVase);感兴趣Console.WriteLine(flowerInVase); 该方法调用自身直到它被条件终止。 只有在堆栈已满之后,它才会弹出上面的每个方法,并且控制台从最少1,2,3开始写入数字。

为什么console.writeline只在堆栈弹出时才起作用,为什么它不是在方法转到终止的方式上写数字,比如3,2,1? 编译器仅在完成递归时才使用writeline。

由于if语句中的行的排序方式,您获得1,2,3。

Main()调用Method(3)
Method(3)在有机会打印“3”之前调用Method(2) 。 执行立即跳转到Method的顶部; 您对花的第一次调用( flowersinvase=3在递归调用之前不会完成。 同样, Method(2)立即调用Method(1)Method(1)调用Method(0)

Method(0)什么也不做,返回到Method(1) ,正好在它停止的地方; 下一行是您的WriteLine调用,它打印“1”然后返回,它接收对Method(2)的调用,它停止,打印“2”,依此类推“3”。

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

调用的结构如下所示。 也许这个可视化将帮助您理解为什么数字打印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); 

原因是因为您调用Method(flowerInVase - 1) 之前是对WriteLine(flowerInVase)的调用。 在有机会打印它所在的数字之前,执行会跳转到该方法的不同副本。

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

这样做是因为你告诉它这样做 。 在您的代码中,首先执行递归(调用Method() ),并且只有在完成后,才能编写数字。

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

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

因为它这样做:

 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?

因为你的Method(flowerInVase - 1); Console.WriteLine(flowerInVase); 之前调用Console.WriteLine(flowerInVase);

如果你逐行遵循代码执行,这是有道理的。 如果你打破它真正的含义是你总是在你有机会向控制台写任何东西之前创建一个新的递归调用实例。 只有在创建了允许的所有调用(if语句失败)后,才能控制返回到现有方法的线程。

 Create method -> check parameter -> create method - > check parameter -> create method -> check parameter etc. etc. -> print value -> print value -> print value 

所以现在你看到它正在以它被调用的方式恢复控制。 最后一个被调用的函数需要在调用它之前完成其操作。

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

如果逐行读取代码,您将看到调用Method(2) ,然后调用Method(2) ,最重要的是,它在输出值3之前进行调用。因此, Method(2)在输出Method(3)的最后一行之前将完整地执行。 同样, Method(2)在输出2之前调用自身,因此整个Method(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()