RememberOfLife RememberOfLife - 3 months ago 6
C# Question

Exiting from a Method by calling another Method

So I want to exit the execution of a method or function by calling for another method. I have so far only found problems with else and nothing like I need.

Example as follows..

public static void SomeMethod() {
// some code
ExitMethod();
// the next line of code will never be executed
Console.WriteLine("Test");
}

private static void ExitMethod() {
// if possible the execution of the Method above will be stopped here
}


The ExitMethod would work like a return statement, only that because it is a method I can more easily add an if or other conditions to it. If I were to use the ExitMethod often in my assembly I could easily refactor the conditions under which execution of the calling Method would be stopped.




This can for example be used in an obviously insecure attempt of securing a dll, so that it requires a serial key and only if the correct one is given it will enable some static bool that then is checked everytime a function is called from the dll.

Thanks in advance :)

EDIT:
By using another method that can be called for the cancellation task I want to avoid something like:

public static void SomeMethod() {
if (ExitMethod) return;
}


The goal is to only be required to call the ExitMethod Method which takes care of things.

Answer

From the comments in the question:

why isn't there a better solution [...]?

Implicit flow-control is generally regarded as an anti-pattern - there are even arguments against exceptions existing at all. Languages that purposefully don't include any form of implicit flow-control exist (e.g. Go).

Here are a few approaches that you could use.

Explicit Flow Control

public bool ExitMethod() => // ...

public void SomeMethod()
{
  if (ExitMethod()) return;
  Console.WriteLine("Test");
}

Without DocComments the boolean return value might be confusing. An enum would result in self-documenting code:

public enum ExitParentStatus : byte
{
  Continue, Return
}

public ExitParentStatus ExitMethod() => // ...

public void SomeMethod()
{
  if (ExitMethod() == ExitParentStatus.Return) return;
  Console.WriteLine("Test");
}

Explicit Flow Control with State

public enum RequestStatus : byte
{
  Processing, Handled
}

public class Request
{
  public RequestStatus Status { get; set; }
}

public void ExitMethod(Request request) => // ...

public void SomeMethod(Request request)
{
  ExitMethod();
  if (request.Status == Handled) return;
  Console.WriteLine("Test");
}

Use Yield Return

This provides clues to other developers that they are approaching poorly designed code, slightly reducing the chances of a bug.

public void ExecuteConditionalCoroutine(IEnumerable<bool> coroutine)
{
  foreach (var result in coroutine)
  {
    if (result) return;
  }
}

public bool ExitMethod() => // ...

public IEnumerable<bool> SomeMethod()
{
  yield return ExitMethod();
  Console.WriteLine("Test");
}

ExecuteConditionalCoroutine(SomeMethod());

Exceptions

Use this if you want to make your code impossible to debug.

public bool ExitMethod() { throw new ExitParentMethodException(); }

public void SomeMethod()
{
  try
  {
    ExitMethod();
    Console.WriteLine("Test");
  }
  catch (ExitParentMethodException) { }
}

Post-Compilation

Use something like post-sharp to automatically inject the branch. This a great approach for completely unmaintainable code.

[ExitsParentMethod]
public bool ExitMethod() => // ...

public void SomeMethod()
{
  ExitMethod();
  Console.WriteLine("Test");
}