BBedit
BBedit

Reputation: 8057

How to fix a StackOverflow exception in Get/Set?

Bear in mind that this is my first day of learning C#; this is also my first compiled language, so I am absolutely not used to the concept of 'types'. I am coming from Python.

It seems strongly typed languages are an order of magnitude more difficult than Python... v_v'

I get a StackOverflow exception, but I don't know why:

    static void Main(string[] args)
    {
        Dictionary<string, int> init = new Dictionary<string,int>();
        init["stepId"] = 250;
        init["offset"] = 13;
        init["inc"] = 113;
        init["danger"] = 0;
        StepGenerator gen = new StepGenerator(init);
        Console.Write("Next: {0}", gen.Step["stepId"]);
        Console.Read();

The error is seemingly here:

    public Dictionary<string, int> Step
    {
        get { return Step; }
        set
        {
            Dictionary<string, int> step = value;
            // It complains about this line, and suggests an infinite recursion.
            step["rnd"] = genRnd(rnlut[step["stepId"]], step["offset"]);
            step["limit"] = genDangerLimit(step["rnd"]);
            step["enc"] = genEnc(step["danger"], step["limit"]);
            Step = step;
        }

Full:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;

    namespace rePlanner
    {
        public class StepGenerator
        {
            // snipped array size:
            private static readonly int[] rnlut = new int[] {0xB1}
        enum Input
        {
            B,
            G,
        };

        enum Encounter
        {
            No,
            Yes,
        }

        enum Type
        {
            Run,
            Walk,
            Stutter,
            Unit,
        }
        public Dictionary<string, int> Step
        {
            get { return Step; }
            set
            {
                Dictionary<string, int> step = value;
                step["rnd"] = genRnd(rnlut[step["stepId"]], step["offset"]);
                step["limit"] = genDangerLimit(step["rnd"]);
                step["enc"] = genEnc(step["danger"], step["limit"]);
                Step = step;
            }
        }
        internal int stepId {get; set;}
        internal int offset { get; set;}
        internal int danger { get; set; }
        internal int rnd { get; set; }
        internal int dangerLimit { get; set; }
        internal int enc { get; set; }
        internal int type { get; set; }
        internal int units { get; set; }
        public int input { get; set; }


        // Constructor.
       public StepGenerator(Dictionary<string, int> step)
        {
            this.Step = step;
        }

        private int genStepId(int oldStepId)
        {
            return (oldStepId + 2) & 0xFF;
        }

        private int genOffset(int oldOffset, int stepId)
        {
            if (stepId == 0)
            {
                int offset = (oldOffset + 13) & 0xFF;
            }
            else
            {
                offset = oldOffset;
            }
            return offset;
        }

        private int genDanger(int oldDanger, int oldInc)
        {
            danger = oldDanger;
            danger += oldInc;
            if (danger > 65535)
            {
                danger = oldInc;
            }
            return danger;
        }

        private int genRnd(int rnlut, int offset)
        {
            return (rnlut - offset) & 0xFF;
        }

        private int genDangerLimit(int rnd)
        {
            return ((rnd + 1) * 256);
        }

        private int genEnc(int danger, int dangerLimit)
        {
            if(danger > dangerLimit)
            {
                return (int)Encounter.Yes;
            }
            return  (int)Encounter.No;
        }

        public Dictionary<string, int> next()
        {
            Dictionary<string, int> step = this.Step;
            step["stepId"] = genStepId(this.Step["stepId"]);
            step["offset"] = genOffset(this.Step["offset"], this.Step["stepId"]);
            step["danger"] = genDanger(this.Step["danger"], this.Step["inc"]);
            step["rnd"] = genRnd(rnlut[step["stepId"]], step["offset"]);
            step["limit"] = genDangerLimit(step["rnd"]);
            step["enc"] = genEnc(step["danger"], step["limit"]);
            this.Step = step;
            return step;
        }

    }
}

Upvotes: 0

Views: 494

Answers (1)

Chris Mantle
Chris Mantle

Reputation: 6693

You're calling the setter on Step repeatedly with with line

Step = step;

This causes infinite recursion.

I think that you need to make your Step property the getter and setter for a private step member variable. First of all, remove

Dictionary<string, int> step = value;

from the Step setter. Make step a private member variable of StepGenerator:

private Dictionary<string, int> step;

Change your Step property to be:

public Dictionary<string, int> Step
{
    get { return this.step; }

    set
    {
        this.step = value;
        this.step["rnd"] = genRnd(rnlut[step["stepId"]], step["offset"]);
        this.step["limit"] = genDangerLimit(step["rnd"]);
        this.step["enc"] = genEnc(step["danger"], step["limit"]);
    }
}

Upvotes: 1

Related Questions