Search code examples
c#classswitch-statementconsole-applicationstack-overflow

Stack overflow exception with instances of classes


In my Main Menu class, I have a switch statement that calls the DisplaySellMenu method in the sell menu class(instance of the sell menu class was created in main menu class) when the user types the number to go to the sell menu. I then created a new instance of the Main menu class in the Sell Menu class, below you can see the switch statement I made so that when the user selects to exit to the Main Menu it calls the DisplayMainMenu method in the MainMenu class so the user can go back to the MainMenu. This is causing a stack overflow exception between the instances of the classes. How do I stop this from happening while still allowing the user to exit back to the main menu?

Main menu class:

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



    }
}

Sell menu class:

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

Solution

  • It seems to me that your SoldItems() case 4 should simply be this:

    case 4:
        return;
    

    You're already calling SoldItems() from DisplayMenu() in MainMenu, so all you need to do is return to the DisplayMenu() switch statement and continue its loop.

    Having an Exit variable is unnecessary here because return will leave the entire method body, terminating the while loop. The same applies to DisplayMenu()'s Exit variable, too.

    Complete code for SoldItems():

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

    Explanation of StackoverflowException:

    This exception is caused when the stack gets full. Imagine you have three methods:

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

    When A calls B, an extra layer is pushed onto the stack. The same happens when B calls C. When C returns to B, that layer is pushed off the stack, and then the same then B returns to A.

    The .NET stack has a finite size, so you can't infinitely call methods. This is typically big enough for any code you write, except recursive functions can be a little dangerous. Imagine this code:

    public void A() { A(); }
    

    It calls itself recursively forever. This code is doomed to experience a Stackoverflow exception. When you write code like this, you need to place a limitation on it to ensure that it only goes so deep. Example:

    public void A(int maxDepth = 0) { if (maxDepth < 5) { A(++maxDepth); } }
    

    You can read more about the stack and this exception here.

    Obligatory Google Easter egg