Reputation: 3
So this is a small piece of c# code mimicking tumbler dials.
Main Program here - Instantiating two Tumblers -- while one of it references the first. The idea is when Tumbler x completes a rotation "resets" and triggers an event that triggers Tumbler y to actuate and increment
class Program
{
public static Tumbler x;
public static Tumbler y;
static void Main(string[] args)
{
x = new Tumbler(10);
y = new Tumbler(x, 20);
while (true)
{
Console.WriteLine(x.Teeth + " " + y.Teeth);
x.Actuate();
Console.ReadKey();
}
}
}
This is the tumbler class - two event handlers that is automatically gets subscribed to when the property LinkedTumbler is filled.
It works as expected until the event is fired -- and "program terminated due to stack overflow"
public class Tumbler
{
private const int DEFAULT_TEETH_MAX = 6;
private const int DEFAULT_LOWEST_TEETHVAL = 1;
private Tumbler linkedtumbler;
private int current_Teeth;
private int max_Teeth;
private const int DEFAULT_TEETH = 1;
public event EventHandler MaxTriggered;
public event EventHandler MinTriggered;
public Tumbler() : this(DEFAULT_TEETH_MAX)
{
}
public Tumbler(int maxTeethValue, int currentTeeth = DEFAULT_TEETH)
{
MaxTeeth = maxTeethValue;
Teeth = currentTeeth;
}
public Tumbler(Tumbler tbLink, int maxTeethValue, int currentTeeth = DEFAULT_TEETH) : this(maxTeethValue, currentTeeth)
{
LinkedTumbler = tbLink;
}
public int Teeth
{
get
{
return this.current_Teeth;
}
private set
{
if(value < DEFAULT_LOWEST_TEETHVAL)
{
if(MinTriggered != null)
MinTriggered(this, new EventArgs());
this.current_Teeth = MaxTeeth;
}
else if (value <= MaxTeeth)
{
this.current_Teeth = value;
}
else
{
if (MaxTriggered != null)
MaxTriggered(this, new EventArgs());
this.current_Teeth = DEFAULT_LOWEST_TEETHVAL;
}
}
}
public int MaxTeeth
{
get
{
return this.max_Teeth;
}
private set
{
this.max_Teeth = value;
}
}
public Tumbler LinkedTumbler
{
get
{
return linkedtumbler;
}
private set
{
linkedtumbler = value;
if (linkedtumbler.MaxTriggered == null)
linkedtumbler.MaxTriggered += Linkedtumbler_MaxTriggered;
}
}
private void Linkedtumbler_MaxTriggered(object sender, EventArgs e)
{
linkedtumbler.Actuate();
}
public void Actuate()
{
Teeth++;
}
public void ReverseActuate()
{
Teeth--;
}
}
Upvotes: 0
Views: 67
Reputation: 1062695
At some point when x.Actuate()
is called, it hits the:
if (MaxTriggered != null)
MaxTriggered(this, new EventArgs());
this.current_Teeth = DEFAULT_LOWEST_TEETHVAL;
region; so - it invokes the event via MaxTriggered
, which is basically y.Linkedtumbler_MaxTriggered;
; this calls straight back into linkedtumbler.Actuate();
, which is effectively x.Actuate();
. And recall that you haven't set this.current_Teeth = DEFAULT_LOWEST_TEETHVAL;
yet (we haven't got that far), so nothing has changed - we're going to keep doing the same thing in a stack-dive until we explode.
Upvotes: 1