调用堆栈如何在C#应用程序中工作(给出简单示例)

时间:2014-02-10 21:50:57

标签: c# recursion

我从未参与算法。目前我失业了所以我决定更多地了解递归以及如何使用它。我已经多次学习基础知识,我知道如何解决像fibonacci numbersfactorial这样的简单问题,但这是因为当有人试图解释递归时,这些问题最常见为例。

然而今天我开始再次制作一个简单的控制台应用程序来计算阶乘,只是为了看看我这次能不能得到更多东西而且我遇到了这种情况,我认为我的理解不仅仅是递归但一般来说堆栈是如何工作的以及为什么事情会按照他们的方式发生,因为这个例子非常简单,我认为这可能是一个完美的基础,我可以尝试找到一些新的方法来解决同样的问题(如何学习自己递归思考。

所以在这里。对于因子计算,我使用这个简单的类/方法从控制台获取数字。我只是觉得没有让一切都变得静止,但没有特别的理由让它像这样,我刚刚做了,所以我最终得到了这个课:

class GetUserInput
{
    public int GetFactorialNumber()
    {
        Console.Write("Enter number: ");
        int number;
        bool result = Int32.TryParse(Console.ReadLine(), out number);
        while (!result)
        {
            Console.WriteLine("Error!");
            GetFactorialNumber();
        }
        return number;
    }
}

在我的Main方法中,我有这个:

GetUserInput GetNumber = new GetUserInput();
int number = GetNumber.GetFactorialNumber();

那会发生什么:

  1. 我启动程序并输入无法解析为int的内容,例如dfgdf,在y调试器中我看到了:
  2. First

    1. 我收到我的Error,我被要求再次输入号码,所以这次我输入有效的号码5,我在调试器中看到了这个:
    2. Second

      1. 我进入无限循环。即使我从现在开始只输入有效的整数,我仍然会看到第一个无效的呼叫:
      2. Three

        这将永远持续下去。无论我从现在开始输入什么,如果它无效,只要输入有效,方法就会停留在Call stack,然后方法被删除,但是一旦输入无效,我就永远不会离开循环数据第一次。

        基于这个简单的例子,你可以解释一下这里发生了什么。说实话,起初我认为这实际上会起作用。我的意思是 - 我得到一个正确的输入,我离开while循环,我点击return,这就是全部,返回,我不在这个方法中。然后,当我看到我进入无限循环时,我试图向自己解释它是什么原因,因为我有一个调用自身的方法我认为我已经创建了某种递归,但这是我得到的地方丢失 - 堆栈是如何工作的以及为什么我无法摆脱它(在这种情况下,但一般情况下)?因为主要的想法是让我理解递归是如何工作的,你能解释一下,Call stack如何工作以及我的代码与它如何相互作用以获得我所描述的结果?

3 个答案:

答案 0 :(得分:2)

为什么不在这里摆脱递归:

public int GetFactorialNumber()
{
    Console.Write("Enter number: ");
    int number;

    while (!Int32.TryParse(Console.ReadLine(), out number))
        Console.WriteLine("Error!");

    return number;
}

如果你想按自己的方式行事:

public int GetFactorialNumber()
{
    Console.Write("Enter number: ");
    int number;
    while (!Int32.TryParse(Console.ReadLine(), out number))
    {
        Console.WriteLine("Error!");

        ** return **GetFactorialNumber(); // Code needs a chance to escape the while
    }
    return number;
}

答案 1 :(得分:1)

    bool result = Int32.TryParse(Console.ReadLine(), out number);
    while (!result)
    {
        Console.WriteLine("Error!");
        GetFactorialNumber();    // here is the problem, no communication with caller
    }
    return number;

这种输入方法不能用于递归,虽然你可以做到这一点,但只需迭代地进行。

对Factorial使用递归是足够人为的(在生产代码中,使用for()循环)。

答案 2 :(得分:0)

要了解行为,请考虑您的代码:

class GetUserInput
{
    public int GetFactorialNumber()
    {
        Console.Write("Enter number: ");
        int number;
        bool result = Int32.TryParse(Console.ReadLine(), out number);
        while (!result)
        {
            Console.WriteLine("Error!");
            GetFactorialNumber();
        }
        return number;
    }
}

第一次输入无效结果。然后为!result执行while循环。由于您传递了无效参数,因此此while循环将永远循环。在你的循环中,你递归地调用GetFactoryalNumber。这将再次询问您在该方法中的另一个输入,但是该结果的结果将限定为递归的该级别。没有什么能够改变外部结果来打破while循环。希望这有助于您理解。