我在抽象类中某个属性的get;
上收到了StackOverflowException。
public abstract class SenseHatSnake
{
private readonly ManualResetEventSlim _waitEvent = new ManualResetEventSlim(false);
protected SenseHatSnake(ISenseHat senseHat)
{
SenseHat = senseHat;
}
protected static ISenseHat SenseHat { get; set; } // This Line
public virtual void Run()
{
throw new NotImplementedException();
}
protected void Sleep(TimeSpan duration)
{
_waitEvent.Wait(duration);
}
}
我正在这里设置并获得它:
public class SnakeGame : SenseHatSnake
{
private readonly int _gameSpeed = 1000;
private static Timer _updatePositionTimer;
private bool _gameOver = false;
public readonly Movement Movement = new Movement(SenseHat);
public readonly Food Food = new Food(SenseHat);
public readonly Body Body = new Body(SenseHat);
public readonly Display Display = new Display(SenseHat);
public readonly Draw Draw = new Draw(SenseHat);
public SnakeGame(ISenseHat senseHat)
: base(senseHat)
{
}
//More code
}
其中一个类如下:
public class Movement : SnakeGame
{
public Movement(ISenseHat senseHat)
: base(senseHat)
{
}
//More code
}
据我所知,StackOverflowException意味着我在某处具有无限循环或无限递归,但老实说,我不知道在哪里,也不知道如何解决它。
答案 0 :(得分:12)
<xsl:for-each select="./*[local-name() = 'Application']/*[local-name() = 'Data']">
<xsl:if test="">
....
</xsl:if>
</xsl:for-each>
中的这一行会导致递归
SnakeGame
由于public readonly Movement Movement = new Movement(SenseHat);
是从Movement
继承的,因此其构造函数将初始化SnakeGame
,再次调用上面的行以初始化自己的SnakeGame
字段。导致递归。
答案 1 :(得分:5)
在其他答案中已经确定了溢出的根源,其他答案也指出了程序草图中的体系结构设计问题。
我想我会简要地说一下如何自己调试此类问题。
首先:面对堆栈溢出时,几乎总是存在无限的递归。如果在一个本来没有堆栈溢出的成员中报告了溢出,那发生了什么?这发生了:
npm install -g npm@latest
如果调用void Bad()
{
Good();
Bad();
}
,则它将堆栈溢出,但是大多数情况下,溢出将在Bad
中报告,因为Good
可能使用< em>更多堆栈比对Good
的任何单个调用都要多。
您需要做的是查看调用堆栈,因为它将是Bad
,并且告诉您Good / Bad / Bad / Bad / Bad ...
正在执行无限制的递归。 找到递归源的关键是找到直接或间接调用自己的东西。使用您可以使用的仪器进行操作;异常包含调用堆栈的痕迹。
答案 2 :(得分:2)
这是一个错误的模式:
protected SenseHatSnake(ISenseHat senseHat)
{
SenseHat = senseHat;
}
protected static ISenseHat SenseHat { get; set; }
// ^^^^^^
您的构造函数正在设置SenseHatSnake
的所有子类之间共享的 static 字段,这意味着最后一个设置该字段的类“获胜”。这也意味着您永远无法设置该字段,因为要构造要分配给该字段的值,您必须创建一个必须设置该字段的对象-一条蛇追逐自己的尾巴。同样,您不能从构造Movement
类型的成员的类派生Movement
作为初始化的一部分。
解决此问题需要对您的课程进行认真的重组:
public class SnakeGame {
private readonly int _gameSpeed = 1000;
private static Timer _updatePositionTimer;
private bool _gameOver = false;
public Movement Movement {get;}
public Food Food {get;}
public Body Body {get;}
public Display Display {get;}
public Draw Draw {get;}
public SnakeGame(ISenseHat senseHat)
{
Movement = new Movement(this);
Food = new Food(this);
Body = new Body(this);
Display = new Display(this);
Draw = new Draw(this);
}
//More code
}
public abstract class GameObject {
protected readonly SnakeGame game;
protected GameObject(SnakeGame game) {
this.game = game;
}
}
public class Movement : GameObject
{
public Movement(SnakeGame game)
: base(senseHat)
{
}
//More code
}
现在GameObject
的子类共享SnakeGame
对象,从而可以访问其属性。