2

这是我的代码

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);方法调用自身感兴趣,直到它被条件终止。只有在那之后,当堆栈已满时,它才会从上面弹出每个方法,并且控制台会从最小的 1、2、3 开始写入数字。

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

4

7 回答 7

10

调用的结构如下所示。也许这个可视化会帮助你理解为什么数字会打印 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)。在有机会打印它所在的数字之前,执行会跳转到该方法的另一个副本。

于 2013-01-30T20:45:15.260 回答
3

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

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

Method(0)什么都不做并返回到Method(1)它停止的地方;下一行是您的WriteLine呼叫,它打印“1”然后返回,它将呼叫接续到Method(2)中断的地方,打印“2”,以此类推“3”。

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

于 2013-01-30T20:51:00.723 回答
2

因为它这样做:

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。

于 2013-01-30T20:45:40.230 回答
1

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

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

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

public static void Method(int flowerInVase)
{
   if (flowerInVase > 0)
   {
       Console.WriteLine(flowerInVase);
       Method(flowerInVase - 1);
   }
}
于 2013-01-30T20:45:07.907 回答
1

为什么console.writeline只有在卡住弹出时才起作用,为什么它没有在方法到达终止的方式上写数字,比如3、2、1?

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

于 2013-01-30T20:45:55.263 回答
0

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

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

所以现在你看到它正在以调用的方式返回控制权。最后调用的函数需要在调用它的函数完成之前完成它的操作。

于 2013-01-30T20:45:36.463 回答
0

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

如果您逐行阅读代码,您会看到Method(3)被调用,它又调用Method(2),最重要的是,它在输出值 3 之前进行此调用。因此,Method(2)将在最后一行 from Method(3)is之前完整执行输出。再一次,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()
于 2013-01-30T20:50:25.447 回答