-4

I have a C# method, if a condition is not met I want to re-run the Main() method. There are a few posts saying use loops to do this. GoTo would also work - but don't use it. Or restart the application.

No one has given a clear newbie-level explanation about the loops.

C# example:

public static void Method3(int userChoice){
 if(userChoice == 1){
  Console.WriteLine("do this");
 }
 else{
  Main(); // How to run the main program again from the start ?
 }
}

public static void Main(string[] args)
{
 Method1();
 int userChoice = Method2();
 Method3(userChoice);  // I want Method3 to go back to Method1() if the else statement is met.
}      

In python this is real easy - you just call Main() from the function.

Scottish Smile
  • 455
  • 7
  • 22
  • 4
    You need to give a clear newbie-level explanation of what you are trying to accomplish, because calling `Main()` from `Main` will probably not do whatever you are thinking of. – Dour High Arch Oct 16 '19 at 23:13
  • Maybe instead of calling method3 just check if userChoice is not 1 in the main method and loop the 1-2 lines above that. – Arundeep Chohan Oct 16 '19 at 23:17
  • 3
    In python if you did that, you would eventually encounter a stack overflow if you went back to Main too many times. – Robert McKee Oct 16 '19 at 23:29
  • It is possible to do something that works like you expect, using tasks. I am not writing it, because it is unnecessary overhead, I do not advise it as a solution for this. – Theraot Oct 16 '19 at 23:41

3 Answers3

2

You can have Method3() return a bool so the Main() method knows whether to try again.

public static bool Method3(int userChoice)
{
    if (userChoice == 1)
    {
        Console.WriteLine("do this");
        return false;
    }

    return true;
}

public static void Main(string[] args)
{
    bool tryAgain;
    do
    {
        Method1();
        int userChoice = Method2();
        tryAgain = Method3(userChoice);
    } while (tryAgain);       
}

Simply calling Main() again instead of looping is another approach, but has some disadvantages.

  • You'll have to come up with the args argument somehow. Maybe it's just an empty array in your case.
  • It's a recursive call and affects the stack trace. After so many recursive calls, your application will crash.
  • It decreases maintainability. You'll have to remember in the future if you want to add anything to the top of the Main() method that you're calling it from somewhere. It lends itself to the introduction of potentially hard-to-diagnose bugs. Using the loop approach encapsulates the behavior. From just looking at Main(), it's obvious that Method3() might cause another loop.
itsme86
  • 19,266
  • 4
  • 41
  • 57
  • 1
    The 3rd bullet is the most important. I'm not sure why I saved it for last. It might be okay for a trivial application like you've shown, but the unexpected recursive call is a 100% unacceptable design where I work. Maintainers would flog a developer for such an approach. – itsme86 Oct 16 '19 at 23:35
1

First of all, yes, you can call Main. Please note that in your example you are missing the args parameters (which would have the command line arguments). Besides that, also know that Main returns, and then execution continues after where you called it. Also, you would very likely end up with a stack overflow. If I recall correctly modern versions of the JIT can optimize tail recursion, yet I do not believe they do for this particular case.


About that newbie-level explanation of a loop... this is an infinite loop, it will run forever:

while(true)
{
    // ...
}

You can exit the loop with break

while(true)
{
    // ...
    if (something)
    {
        break;
    }
    // ...
}

Or you can change that true for a conditional:

while(!something)
{
    // ...
}

The idea would be to wrap Main in a loop, so that it would continue to run until a condition is met. You could have another method and call it in the loop, for example:

public static bool Execute()
{
    if (something)
    {
        // do whatever
        return true;
    }
    return false;
}

public static void Main(string[] args)
{
    while (!Execute())
    {
        // Empty
    }
}

There are, of course, other kinds of loops aside from the while loop, they are the do...while loop, for loop, and foreach loop.


Goto would work? Arguably. The idea is that you can use goto to control the flow of execution to back in the method. That is:

label:
// ...
goto label;

The above code is an infinite loop. You can, of course, introduce a condition:

label:
// ...
if (!something)
{
    goto label;
}
// ...

The while can do – sometimes with the help of a variable – whatever you can do with goto, and it is usually easier to read and less error prone.


Restarting the process is a bit more tricky, you need to use Process.Start to run your own executable. See What is the best way to get the executing exe's path in .NET?.

Theraot
  • 31,890
  • 5
  • 57
  • 86
0

So it's not really hard to do but you can just use a while loop.

C#:

public static void Main(string[] args)
{
     while(true)
     {
          Method1();
          int userChoice = Method2();
          Method3(userChoice);
     }
}

That would give you what you want and if you want to exit you just put

break;
  • 2
    How is OP supposed to know if they want to exit if the logic for that is in `Method3()` and it doesn't return a value? – itsme86 Oct 16 '19 at 23:38