Recursive method not restarting

leorob88

Well-known member
Joined
Dec 31, 2020
Messages
56
Programming Experience
1-3
I'm not understanding why and I don't find any resources explaining clearly where the issue should be, when I try to recall a method (not a function). I'm asking for specific help or code, not some general conceptual advice, I would need some actual help to understand how to achieve what I need, if I don't get a practical example I suppose I'll never understand.
I have a method following a bunch of instructions and when I reach some point I have a check/statement: if the condition is met -> restart the whole code of this method.
From what I read online it should be easy as that but it actually doesn't work.
The first approach was inside the Click event of a Button, so in the check condition part it was just
C#:
if (condition) { button1.PerformClick();
What happens is just the instruction seems to be ignored although it gets read (tried to debug with breakpoints).
I also tried with an if-else statement, like
C#:
if (condition) { button1.PerformClick(); } else { go on with the remaining part }
I also tried to use different instructions like
C#:
button1.Invoke(new Action(() => { button1.PerformClick(); }));
or
C#:
button1_Click(button1, EventArgs.Empty);
but none worked. I also tried moving the full code in a private void, so the button would call the void method and so would do the method as well, but not even that worked. Can someone give a piece of advice to understand how this works or why it doesn't? It seems total nonsense to me it's so difficult to perform such a basic instruction.
 
Line 29 will not be reached until previous calls are finished, and they never will. You get infinite recursion and end up with stack overflow exception.

That's my point. In the other project this doesn't happen (and I want it to happen). The perform button instruction gets read but actually ignored and the rest of the code below gets executed and instead I WANT it to restart if the specific condition is met.
 
In the end i changed approach and i'm using goto instead. Still, it would be nice to understand what prevents a recursion from happening.
 
You don't want recursion if you want it to start over. You want iteration.

This:
C#:
private void button1_Click(object sender, EventArgs e)
{
    Obj obj1 = objs[0];
    Obj obj2 = objs[1];
    obj1.name = "nay";
    obj2.name = "nay";
    if (obj1.name == "nay" && obj2.name == "nay")
    {
       button1.PerformClick();
    }
    MessageBox.Show("ok");
}

should be written as:
C#:
private void button1_Click(object sender, EventArgs e)
{
    Obj obj1;
    Obj obj2;

    do
    {
        obj1 = objs[0];
        obj2 = objs[1];
        obj1.name = "nay";
        obj2.name = "nay";
    } while (obj1.name == "nay" && obj2.name == "nay")

    MessageBox.Show("ok");
}

No need for goto.
 
In the end i changed approach and i'm using goto instead. Still, it would be nice to understand what prevents a recursion from happening.

The perform button instruction gets read but actually ignored and the rest of the code below gets executed

I am sure of the condition and for 2 reasons: 1.the code runs the instructions inside the "if" statement and 2.i checked the values and they actually are what triggers the "if" statement. as long as I know, there's no validation (unless the only one I can think of? meaning the first instructions set to "" some text controls of the form).

Use your debugger. Trace into the .NET Framework.

1716735351603.png


To do this you'll need to change your debugger settings:
1716735475840.png


1716735545886.png


Set a breakpoint on your PerformClick() call:
1716735725058.png


Run your code. When you hit the breakpoint, press F11 to step in.
1716735793620.png


When you step into the PerformClick(), on my machine it goes into CanSelectCore(), but if you press Shift-F11 to step out, it'll take you to the next line of PerformClick().

If your breakpoint is never hit, that suggests that your condition is not true like you've been asserting.
 
Also more proof that you likely want iteration instead of recursion. Consider what happens when coming back up the call stack from recursion. You said that if the condition is not meant you want to start over. So if you start over 10 times, do you also want to the the steps after the condition to also be performed 10 times?

C#:
using System;
using System.Windows.Forms;
using System.Drawing;
using System.Reflection;

namespace WinForms
{
    class MainForm : Form
    {
        const int MaxCount = 10;

        Button m_btnRecurse;
        Button m_btnIterate;
        Button m_btnReset;
        int m_count = 0;

        MainForm()
        {
            m_btnRecurse = new Button()
            {
                Text = "Recurse"
            };
            m_btnRecurse.Click += btnRecurse_Click;

            m_btnIterate = new Button()
            {
                Text = "Iterate"
            };
            m_btnIterate.Click += btnIterate_Click;

            m_btnReset = new Button()
            {
                Text = "Reset"
            };
            m_btnReset.Click += (o, e) =>
            {   m_count = 0;
                Text = "";
            };

            var layout = new FlowLayoutPanel() { Dock = DockStyle.Fill };
            Controls.Add(layout);
            layout.Controls.Add(m_btnRecurse);
            layout.Controls.Add(m_btnIterate);
            layout.Controls.Add(m_btnReset);
        }

        void btnRecurse_Click(object sender, EventArgs e)
        {
            m_count++;
            Text = $"Recurse count = {m_count}";
            if (m_count < MaxCount)
            {
                m_btnRecurse.PerformClick();
            }
            MessageBox.Show("Done!");
        }

        void btnIterate_Click(object sender, EventArgs e)
        {
            while (m_count < MaxCount)
            {
                m_count++;
                Text = $"Recurse count = {m_count}";
            }
            MessageBox.Show("Done!");
        }

        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new MainForm());
        }
    }
}
 
Use your debugger. Trace into the .NET Framework.

View attachment 3172

To do this you'll need to change your debugger settings:
View attachment 3173

View attachment 3174

Set a breakpoint on your PerformClick() call:
View attachment 3175

Run your code. When you hit the breakpoint, press F11 to step in.
View attachment 3176

When you step into the PerformClick(), on my machine it goes into CanSelectCore(), but if you press Shift-F11 to step out, it'll take you to the next line of PerformClick().

If your breakpoint is never hit, that suggests that your condition is not true like you've been asserting.

I see you still don't understand that the breakpoint gets hit. I've been telling the whole time...
 
So if you start over 10 times, do you also want to the the steps after the condition to also be performed 10 times?

No, in fact that's not how recursion should work. Recursion should be just a reiteration of a method/function from the beginning through a call of itself, provided that you also must be aware of stating a condition to do/not do that. I assume by logic and experience with JS that recursion doesn't care about successive instructions, if a call is made. Still, as I said, I changed approach and I used "goto" instead.
 
I see you still don't understand that the breakpoint gets hit. I've been telling the whole time...

And what did setting the breakpoint and tracing into the .NET Framework code tell you? Did the framework code make it all the way to the call to OnClick()? Or did it ball out early because the checks for focus, ability to select, or form validation failed. You said you really wanted to find out why the recursive call was not working. Then really do some debugging.
 
I assume by logic and experience with JS that recursion doesn't care about successive instructions, if a call is made.

Recursion in JavaScript works the same was as recursion in C#. Successive instructions are executed. Consider the following JavaScript which computes factorials.
JavaScript:
function factorial(n) {
  child = 1;
  if (n > 1) {
    child = factorial(n - 1);
  }
  level = n * child;
  return level;
}

console.log(factorial(5));

If lines 6 and 7 are never executed after line 4 is executed, then you would get the incorrect computation for factorial(5).
 
And what did setting the breakpoint and tracing into the .NET Framework code tell you? Did the framework code make it all the way to the call to OnClick()? Or did it ball out early because the checks for focus, ability to select, or form validation failed. You said you really wanted to find out why the recursive call was not working. Then really do some debugging.

Not worth it in the end. Before I got that reply, I already started using goto and fixed it all. Still, yeah, the breakpoints passed through the instructions but didn't execute it. More clear than this, I don't know how to say it.
 
Recursion in JavaScript works the same was as recursion in C#. Successive instructions are executed. Consider the following JavaScript which computes factorials.
JavaScript:
function factorial(n) {
  child = 1;
  if (n > 1) {
    child = factorial(n - 1);
  }
  level = n * child;
  return level;
}

console.log(factorial(5));

If lines 6 and 7 are never executed after line 4 is executed, then you would get the incorrect computation for factorial(5).

whch language is this? JS? anyway, my take would be it repeats until I say so, meaning, recursion shouldn't be used only for "operating values". also, this is a function, not a method, I'm talking about a method in C#, not a function in JS. It seems obvious but my take is "just because the base logic seems similar, it doesn't mean they work in the same way". In fact, half of the problem is online I found almost nothing about recursive methods, most talk about methods but then make functions examples instead.
 
That is JavaScript in post #24.

Methods and functions are the same. What C# calls methods are what C++ and JavaScript call functions. The are all subroutine calls. Some languages make the distinction between methods and function by saying that methods do not return values while functions return values. C# doesn't make that distinction. To C# everything is a method regardless whether it returns a value or not. But in all cases, a subroutine is called and the subroutine returns back to the point when the call was invoked.

Here's that same code from post #24 as C#:
C#:
using System;

class Program
{
    static int Factorial(int n)
    {
        int child = 1;
        if (n > 1)
        {
            child = Factorial(n - 1);
        }
        int level = n * child;
        return level;
    }

    static void Main()
    {
        Console.WriteLine(Factorial(5));
    }
}

You can play with it on .NET Fiddle: https://dotnetfiddle.net/TPlQFc
 
Last edited:
Of if you are still unconvinced because "methods and functions are different" here's another example using what you call "methods":
C#:
using System;

class Program
{
    static int n = 0;
    static int depth = 0;

    static void CountUp()
    {
        int saved = n;

        depth++;
        Console.WriteLine($"Enter n: {n}, saved: {saved}, depth: {depth}");

        n++;
        if (n < 10)
        {
            Console.WriteLine(n);
            CountUp();
        }

        Console.WriteLine($"Leave n: {n} saved: {saved}, depth: {depth}");
        depth--;
    }

    static void Main()
    {
        CountUp();
    }
}

You can play with this on .NET Fiddle: Recursive method | C# Online Compiler | .NET Fiddle
 
Back
Top Bottom