Исключение переполнения стека с экземплярами классов - PullRequest
0 голосов
/ 01 сентября 2018

В моем классе главного меню у меня есть оператор switch, который вызывает метод DisplaySellMenu в классе меню на продажу (экземпляр класса меню на продажу был создан в классе главного меню), когда пользователь вводит число для перехода в меню на продажу. , Затем я создал новый экземпляр класса Main menu в классе Sell Menu, ниже вы можете увидеть оператор switch, который я сделал, чтобы, когда пользователь выбирает выход в главное меню, он вызывал метод 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 голосов
/ 01 сентября 2018

Мне кажется, что ваш SoldItems() вариант 4 просто должен быть таким:

case 4:
    return;

Вы уже вызываете SoldItems() из DisplayMenu() в MainMenu, поэтому все, что вам нужно сделать, это вернуться к оператору переключения DisplayMenu() и продолжить его цикл.

Наличие переменной Exit здесь не нужно, поскольку return оставляет все тело метода, завершая цикл while. То же самое относится и к переменной DisplayMenu() Exit.

Полный код для 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);
}

Объяснение StackoverflowException:

Это исключение возникает, когда стек заполняется. Представьте, что у вас есть три метода:

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

Когда A вызывает B, в стек помещается дополнительный слой. То же самое происходит, когда B вызывает C. Когда C возвращается к B, этот уровень выталкивается из стека, а затем тот же самый, тогда B возвращается к A.

Стек .NET имеет конечный размер, поэтому вы не можете бесконечно вызывать методы. Это обычно достаточно для любого кода, который вы пишете, за исключением того, что рекурсивные функции могут быть немного опасными. Представьте себе этот код:

public void A() { A(); }

Он называет себя рекурсивно навсегда. Этот код обречен на исключение Stackoverflow. Когда вы пишете такой код, вам нужно наложить ограничение на него, чтобы он был настолько глубоким. Пример:

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

Вы можете узнать больше о стеке и этом исключении здесь .

Обязательное гугл пасхальное яйцо

...