简体   繁体   English

类实例的堆栈溢出异常

[英]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. 在主菜单类中,当用户键入要转到销售菜单的数字时,我有一个switch语句,该语句调用卖方菜单类中的DisplaySellMenu方法(卖方菜单类的实例是在主菜单类中创建的)。 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. 然后,我在Sell Menu类中创建了Main菜单类的新实例,您可以在下面看到我所做的switch语句,以便当用户选择退出到Main Menu时,它将调用MainMenu类中的DisplayMainMenu方法,以便用户可以回到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);
    }
}

It seems to me that your SoldItems() case 4 should simply be this: 在我看来,您的SoldItems()情况4应该只是这样:

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. 您已经在MainMenu DisplayMenu()中调用SoldItems() ,因此您所要做的就是返回DisplayMenu()开关语句并继续其循环。

Having an Exit variable is unnecessary here because return will leave the entire method body, terminating the while loop. 这里没有Exit变量是多余的,因为return将离开整个方法主体,并终止while循环。 The same applies to DisplayMenu() 's Exit variable, too. 同样适用于DisplayMenu()Exit变量。

Complete code for SoldItems() : 完整的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: 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. 当A调用B时,一个额外的层被压入堆栈。 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. 当B调用C时,也会发生同样的情况。当C返回到B时,该层被推离堆栈,然后相同的层又返回到A。

The .NET stack has a finite size, so you can't infinitely call methods. .NET堆栈的大小是有限的,因此您不能无限地调用方法。 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. 这段代码注定会遇到Stackoverflow异常。 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 必填Google复活节彩蛋

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM