2

I've create the following class in Visual Studio 2010:

public class Bat : Form1
    {
        public int BatLocation;

        public void draw()
        {
            Pen batPen = new Pen(Color.Black);
            batPen.Width = 10;
            playArea.DrawRectangle(batPen, BatLocation, (picPlayArea.Height - 30), 50, 10);
        }
    }

But when I try to create an instance of the class, I get a stack overflow exception, advising me to make sure that I don't have an infinite loop or infinite recursion. I have tried creating the instance two different ways, as below:

Bat bottomBat;
bottomBat = new Bat();

and

Bat bottomBat = new Bat();

But both ways return the same error when I try to run the program. I've also tried the class definition with and without the public modifier.

I'm pretty new to programming and have no idea what might be causing this problem. Am I doing something wrong?

Edit: The code for the Bat class is everything I have at the moment, haven't created a specific constructor for it... Didn't think I needed to?

Anyway, here is the Form1 class in its entirety:

public partial class Form1 : Form
    {
        // Define various objects for the game
        public Graphics playArea;
        Bat bottomBat = new Bat();


        public Form1()
        {
            InitializeComponent();

            // Create instances of objects
            playArea = picPlayArea.CreateGraphics();
            //bottomBat = new Bat();

            // Delegate the mouseMove event for picPlayArea
            picPlayArea.MouseMove += new MouseEventHandler(picPlayArea_MouseMove);


        }

        private void picPlayArea_MouseMove(object sender, MouseEventArgs e)
        {
            bottomBat.Location = e.X;
        }

        private void btnExit_Click(object sender, EventArgs e)
        {
            string msg = "Are you sure you want to exit?",
                   title = "Confirm Exit";

            DialogResult res = MessageBox.Show(msg, title, MessageBoxButtons.YesNo, MessageBoxIcon.Question);
            if (res == DialogResult.Yes)
            {
                Environment.Exit(0);
            }
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            // This is where most of the functionality is executed within the game
            playArea.Clear(Color.White);
        }

        private void btnStart_Click(object sender, EventArgs e)
        {
            timer1.Enabled = true;
        }
    }
3
  • 3
    There isn't enough information here. Can you post the code for all of the constructors of the class as well as those of its base-classes? (You can stop once you hit a base-class that is a BCL class) Commented Nov 20, 2010 at 9:27
  • The code you posted (minus the line referencing playArea) works just fine for me, so the problem must lie in one of the portions you didn't post. Commented Nov 20, 2010 at 9:30
  • I've added in the code for the Form1 class, as requested Commented Nov 20, 2010 at 9:36

3 Answers 3

5

It appears you have combined inheritance and composition in an impossible sort of way. The base Form1 type has a field declared to be of the derived Bat type. In addition, it uses a field-initializer to initialize it to a new instance of that type. Clearly, you have a turtles-all-the-way-down issue: when you create a Bat (or a Form1 for that matter), the field-initializer will run - this will create an instance of another Bat, which in turn will create yet another Bat, and so on, ad-infinitum in theory. (in practice: until you run out of stack-space).

Here's a simple fix that should solve the stack-overflow issue, but may not be the most appropriate design in the 'big-picture':

public class Bat 
{
   public void Draw(Graphics playArea)
   {
       ...
   }
}

Notice how this type no longer subclasses Form1; it inherits directly from System.Object. Now neither the Form1 nor the Bat classes will exhibit infinite recursion when instances of them are created.

It's hard to suggest the best fix without knowing the ultimate aim here. I suggest you give some thought to the best way to design these classes. I would think you need to spend some time learning about the C# programming language, OO design, as well as WinForms specifics. I think you're actually looking to override the OnPaint virtual method here.

Sign up to request clarification or add additional context in comments.

3 Comments

In that case, how would I then gain access to the playArea object within Form1? I already have it as public, but when I remove the : Form1 from the Bat class, I can no longer access that variable.
@Saladin: You need to access the playArea object through an instance of Form1 in your Bat class. For example: myForm1.playArea
@Saladin if Bat extends Form1, then any bat created see its own playArea, not one from the form it's in
0

Often the cause is confusing a property with its backing variable.

Something along the lines of:

public class tmp 
{ 
    private int _x; 

    ...

    public int X(x)
    {
        X = x;
    }

Comments

0

You have a simple problem.

your class Bat is derived from Form1, and in Form1 you create a new instance of Bat, which in turn is based on Form1 so that creates a new instance of Bat.... and so it repeats until your stack space is used up.

In general, Form1 probably should not know about the class Bat, and that all code that needs to know about Bat should be in the Bat class. However, in exceptional circumstances, you can solve this issue like this:

partial class Form1
{
  public Form1(Bat _bat)
  {
    mBat = _Bat;
  }

  protected Bat mBat;
}

and on the Bat class

public class Bat : Form1
{
  public Bat() :  base(this)
  {

  }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.