类 实例的堆栈溢出异常
Stack overflow exception with instances of classes
在我的主菜单 class 中,我有一个 switch 语句调用出售菜单中的 DisplaySellMenu 方法 class(出售菜单 class 的实例是在主菜单中创建的class) 当用户键入数字以转到销售菜单时。然后,我在销售菜单 class 中创建了主菜单 class 的新实例,您可以在下面看到我所做的开关语句,以便当用户选择退出到主菜单时,它会调用 DisplayMainMenu MainMenu class 中的方法,以便用户可以返回 MainMenu。这会导致 classes 的实例之间发生堆栈溢出异常。如何阻止这种情况发生,同时仍允许用户退出并返回主菜单?
主菜单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);
}
}
销售菜单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);
}
}
在我看来,您的 SoldItems()
案例 4 应该是这样的:
case 4:
return;
您已经在 MainMenu
中从 DisplayMenu()
调用 SoldItems()
,因此您需要做的就是 return 到 DisplayMenu()
switch 语句和继续循环。
这里不需要 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);
}
WhosebugException 的解释:
这个异常是栈满的时候引起的。假设您有三种方法:
public void A() { B(); }
public void B() { C(); }
public void C() { }
当A调用B时,一个额外的层被压入堆栈。当 B 调用 C 时也会发生同样的情况。当 C returns 到 B 时,该层被压出堆栈,然后 B returns 到 A.
.NET 堆栈的大小是有限的,因此您不能无限地调用方法。这对于您编写的任何代码来说通常都足够大,除了递归函数可能有点危险。想象一下这段代码:
public void A() { A(); }
它永远递归地调用自己。这段代码注定会遇到 Whosebug 异常。当您编写这样的代码时,您需要对其进行限制,以确保它不会深入。示例:
public void A(int maxDepth = 0) { if (maxDepth < 5) { A(++maxDepth); } }
您可以阅读有关堆栈和此异常的更多信息here。
在我的主菜单 class 中,我有一个 switch 语句调用出售菜单中的 DisplaySellMenu 方法 class(出售菜单 class 的实例是在主菜单中创建的class) 当用户键入数字以转到销售菜单时。然后,我在销售菜单 class 中创建了主菜单 class 的新实例,您可以在下面看到我所做的开关语句,以便当用户选择退出到主菜单时,它会调用 DisplayMainMenu MainMenu class 中的方法,以便用户可以返回 MainMenu。这会导致 classes 的实例之间发生堆栈溢出异常。如何阻止这种情况发生,同时仍允许用户退出并返回主菜单?
主菜单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);
}
}
销售菜单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);
}
}
在我看来,您的 SoldItems()
案例 4 应该是这样的:
case 4:
return;
您已经在 MainMenu
中从 DisplayMenu()
调用 SoldItems()
,因此您需要做的就是 return 到 DisplayMenu()
switch 语句和继续循环。
这里不需要 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);
}
WhosebugException 的解释:
这个异常是栈满的时候引起的。假设您有三种方法:
public void A() { B(); }
public void B() { C(); }
public void C() { }
当A调用B时,一个额外的层被压入堆栈。当 B 调用 C 时也会发生同样的情况。当 C returns 到 B 时,该层被压出堆栈,然后 B returns 到 A.
.NET 堆栈的大小是有限的,因此您不能无限地调用方法。这对于您编写的任何代码来说通常都足够大,除了递归函数可能有点危险。想象一下这段代码:
public void A() { A(); }
它永远递归地调用自己。这段代码注定会遇到 Whosebug 异常。当您编写这样的代码时,您需要对其进行限制,以确保它不会深入。示例:
public void A(int maxDepth = 0) { if (maxDepth < 5) { A(++maxDepth); } }
您可以阅读有关堆栈和此异常的更多信息here。