C# 尾递归调用与迭代(循环)
本文关键字:循环 迭代 尾递归 调用 | 更新日期: 2023-09-27 18:36:03
我正在开发一个扑克应用程序,我几乎已经完成了它,我正在寻找改进,我想知道的一件事是我应该改变我的主要循环方法方法吗?目前它通过使用尾递归调用进行循环。但是,我的朋友建议我将其切换到迭代,因为它使用的是while循环,而循环不需要堆栈空间。这是我现在的代码。
private async Task Turns()
{
_turns = ReturnTurns();
GC.KeepAlive(Updates);
if (!Player.FoldTurn && Player.Chips > 0)
{
if (Player.Turn)
{
SetPlayerStuff(true);
Call -= Player.PreviousCall;
_up = int.MaxValue;
_turnCount++;
Bot1.Turn = true;
_restart = true;
}
}
if (!Player.Turn)
{
await Flip(0);
}
if (Player.FoldTurn || !Player.Turn || Player.Chips <= 0)
{
Call = TempCall;
if (StatusLabels[Player.EnumCasted].Contains(RepetitiveVariables.Fold))
{
Bot1.Turn = true;
}
SetPlayerStuff(false);
Bot1 = (Bot)await RotateTurns(Bot1, Bot1.EnumCasted);
Bot2 = (Bot)await RotateTurns(Bot2, Bot2.EnumCasted);
Bot3 = (Bot)await RotateTurns(Bot3, Bot3.EnumCasted);
Bot4 = (Bot)await RotateTurns(Bot4, Bot4.EnumCasted);
Bot5 = (Bot)await RotateTurns(Bot5, Bot5.EnumCasted);
_restart = false;
}
if (!_restart)
{
await Turns();
}
}
这就是我认为它应该看起来像循环的样子:
private async Task Turns()
{
while (true)
{
_turns = ReturnTurns();
GC.KeepAlive(Updates);
if (!Player.FoldTurn && Player.Chips > 0)
{
if (Player.Turn)
{
SetPlayerStuff(true);
Call -= Player.PreviousCall;
_up = int.MaxValue;
_turnCount++;
Bot1.Turn = true;
_restart = true;
}
}
if (!Player.Turn)
{
await Flip(0);
}
if (Player.FoldTurn || !Player.Turn || Player.Chips <= 0)
{
Call = TempCall;
if (StatusLabels[Player.EnumCasted].Contains(RepetitiveVariables.Fold))
{
Bot1.Turn = true;
}
SetPlayerStuff(false);
Bot1 = (Bot) await RotateTurns(Bot1, Bot1.EnumCasted);
Bot2 = (Bot) await RotateTurns(Bot2, Bot2.EnumCasted);
Bot3 = (Bot) await RotateTurns(Bot3, Bot3.EnumCasted);
Bot4 = (Bot) await RotateTurns(Bot4, Bot4.EnumCasted);
Bot5 = (Bot) await RotateTurns(Bot5, Bot5.EnumCasted);
_restart = false;
}
if (!_restart)
{
continue;
}
break;
}
}
通常,JIT 无法用循环替换递归。这是一个相当深奥的优化方案。
在这里,这甚至没有发挥作用,因为异步方法在内部使用非常不同的调用机制。
此代码将消耗与递归深度成比例的"堆栈空间"。(它不一定是异步方法的堆栈空间。可以是链表形式的堆空间。
从代码质量的角度来看,我发现循环非常可取,因为递归不是大多数人习惯的。在这里,实际上不需要递归的算法。似乎是这项工作的错误工具。我认为您在这里使用递归作为"goto"的替代品,因为所做的只是跳回到方法的开头。
你可以让跳跃条件更干净一点:
if (!_restart) break;