类实例的堆栈溢出异常

时间:2018-09-01 02:33:47

标签: c# class switch-statement console-application stack-overflow

在主菜单类中,当用户键入要转到销售菜单的数字时,我有一个switch语句,该语句调用卖方菜单类中的DisplaySellMenu方法(卖方菜单类的实例是在主菜单类中创建的) 。然后,我在Sell Menu类中创建了Main菜单类的新实例,您可以在下面看到我所做的switch语句,以便当用户选择退出到Main Menu时,它将调用MainMenu类中的DisplayMainMenu方法,以便用户可以回到MainMenu。这导致类实例之间的堆栈溢出异常。如何阻止这种情况发生,同时仍然允许用户退出到主菜单?

主菜单类:

class MainMenu
{
    public BuyMenu buyMenu = new BuyMenu();
    public SellMenu sellMenu = new SellMenu();
    public ShipGarage shipGarage = new ShipGarage();
    int Exit = 0;

    public void DisplayMenu()
    {           
        Console.WriteLine("Whatcha tryin to do yo?");
        Console.WriteLine("Type 1 to buy");                  
        Console.WriteLine("Type 2 to sell");                 
        Console.WriteLine("Type 3 for SpaceShip Upgrade ");                  
        Console.WriteLine("Type 4 to quit game");
        int userSelection = int.Parse(Console.ReadLine());

        do
        {
            switch (userSelection)
            {                
                case 1:
                    buyMenu.DisplayInventory(buyMenu);
                    DisplayMenu();
                    break;

                case 2:
                    sellMenu.SoldItems();
                    DisplayMenu();
                    break;

                case 3:
                    shipGarage.DisplayGarage(shipGarage);
                    DisplayMenu();
                    break;

                case 4:
                    Exit += 1;
                    break;

                default:
                    Console.WriteLine("Invalid Input");
                    break;
            }
        } while (Exit == 1);



    }
}

出售菜单类别:

class SellMenu
{

    static Random rnd = new Random();
    MoneyMath Money = new MoneyMath();
    MainMenu MainMenu = new MainMenu();
    int goldPrice = rnd.Next(100, 1001);
    int silverPrice = rnd.Next(100, 1001);
    int titaniumPrice = rnd.Next(100, 1001);
    int Exit = 0;


    public string DisplayInventory()
    {
        Console.WriteLine("What would you like to sell?");
        Console.WriteLine("Type 1 for Gold");
        Console.WriteLine("Type 2 for Silver");
        Console.WriteLine("Type 3 for Titanium");
        Console.WriteLine("Type 4 for Main Menu");

        string itemList = "Gold"     + "   " + "$" + (goldPrice)   + "\n" +
                          "Silver"   + "   " + "$" + (silverPrice) + "\n" +
                          "Titanium" + "   " + "$" + (titaniumPrice);

        Console.WriteLine(itemList);
        return itemList;
    }

    public void SoldItems()
    {
        do
        {
            DisplayInventory();
            int userSelection = int.Parse(Console.ReadLine());
            switch (userSelection)
            {
                case 1:
                    Money.MoneyAddition(goldPrice, 1);
                    Console.WriteLine(Money.userMoney);
                    break;
                case 2:
                    Money.MoneyAddition(silverPrice, 1);
                    Console.WriteLine(Money.userMoney);
                    break;
                case 3:
                    Money.MoneyAddition(titaniumPrice, 1);
                    Console.WriteLine(Money.userMoney);
                    break;
                case 4:
                    Exit += 1;
                    MainMenu.DisplayMenu();
                    break;
                default:
                    Console.WriteLine("Invalid Input");
                    break;
            }
        } while (Exit == 1);
    }
}

1 个答案:

答案 0 :(得分:0)

在我看来,您的SoldItems()案例4应该只是这样:

case 4:
    return;

您已经在SoldItems()中从DisplayMenu()调用MainMenu,所以您要做的就是返回DisplayMenu() switch语句并继续其循环。

这里不需要使用Exit变量,因为return会离开整个方法主体,从而终止while循环。 DisplayMenu()的{​​{1}}变量也是如此。

Exit的完整代码:

SoldItems()

StackoverflowException的解释:

此异常是在堆栈已满时引起的。想象一下,您有三种方法:

public void SoldItems()
{
    do
    {
        DisplayInventory();
        int userSelection = int.Parse(Console.ReadLine());
        switch (userSelection)
        {
            case 1:
                Money.MoneyAddition(goldPrice, 1);
                Console.WriteLine(Money.userMoney);
                break;
            case 2:
                Money.MoneyAddition(silverPrice, 1);
                Console.WriteLine(Money.userMoney);
                break;
            case 3:
                Money.MoneyAddition(titaniumPrice, 1);
                Console.WriteLine(Money.userMoney);
                break;
            case 4:
                return;
            default:
                Console.WriteLine("Invalid Input");
                break;
        }
    }
    while (true);
}

当A调用B时,一个额外的层被压入堆栈。当B调用C时,也会发生同样的情况。当C返回到B时,该层被推离堆栈,然后相同的层又返回到A。

.NET堆栈的大小是有限的,因此您不能无限地调用方法。对于递归函数而言,这通常足以容纳您编写的任何代码,但递归函数可能会有些危险。想象一下这段代码:

public void A() { B(); }
public void B() { C(); }
public void C() { }

它永远递归调用。这段代码注定会遇到Stackoverflow异常。当您编写这样的代码时,您需要对其进行限制,以确保其作用范围如此之深。示例:

public void A() { A(); }

您可以了解有关堆栈和此异常here的更多信息。

Obligatory Google Easter egg