5

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.

RememberOfLife
  • 106
  • 1
  • 9
  • 2
    I am sorry but i dont understand.. Why don't you want to use an if-statement? – StarterPack Aug 24 '16 at 14:48
  • 3
    How about throwing an exception in `ExitMethod()`? Or you could make `ExitMethod` return a `bool` and use it like `if (ExitMethod()) return;`. – René Vogt Aug 24 '16 at 14:48
  • I want to avoid using if statements ouside of the ExitMethod otherwise I know what to do. I just want to know if there is an other solution to this than if or an exception.. I have thought about those. – RememberOfLife Aug 24 '16 at 14:50
  • You can use return type for the method 'ExitMethod' as bool and use it like if(ExitMethod()){// the next line of code will never be executed Console.WriteLine("Test");} – Pradeep Aug 24 '16 at 14:50
  • 1
    I think you should reconsider this approach. If you don't want a return value then by all means, don't have one, it isn't required. But if you want to go this route to add conditional logic in the ExitMethod, you will also have to add conditional logic to the SomeMethod (and all other methods invoking ExitMethod) so that the code you want never to execute is skipped in some instances and not others. This invites a confusing design, increases the code necessary when there is a more direct path. It would be better to apply your conditional and return true or false, and process from there. – GrayFox374 Aug 24 '16 at 14:58
  • Can I ask why you want to do this? In your example regarding an insecure DLL access attempt, I believe the correct thing would be to throw an exception as @RenéVogt suggested. – saarrrr Aug 24 '16 at 15:00
  • The short answer to this is simply "no, you can't do that". The longer, far more complicated and why-would-you-really-want-to-go-this-route answer would be to use something like [PostSharp](https://www.postsharp.net/) or some custom Roslyn extensions to get this to work. – James Thorpe Aug 24 '16 at 15:02
  • You could rewrite `SomeMethod` and `ExitMethod` to take explicit continuation parameters and call those. However C# support delimited continuations in the form of exceptions so that might be the most elegant approach. – Lee Aug 24 '16 at 15:04
  • SomeMethod would never need to contain any contionals in combination with the call of ExitMethod as when ExitMethod decides to not go further it returns execution to wherever SomeMethod was called from. Otherwise it skips the part of exiting and just returns to where it was called from and further executes the contents of SomeMethod. – RememberOfLife Aug 24 '16 at 15:05
  • Would you mind editing your question and adding WHY you want to do this? I ask for 2 reasons. First, knowing why you're asking for a very unusual construct might allow the community to provide you with a better solution that you have not considered. Second, the construct that you're asking for leads to what we used to call, "spaghetti code" back in the bad old days of GOTOs and such. These constructs make code difficult to debug. And I doubt that you want the headaches that will come from that. – DeadZone Aug 24 '16 at 15:12
  • First: A possible application of such an Exiting Method is described in the bottom part of the question. Second: Throwing an exeption is a reasonable solution, thus why isn't there a better solution without throwing an exception or that the only way? I think that when errors become your friend there must be something going wrong with what you are trying to do, or the solutions available to fix that. Might be my approach is bad, we will see. – RememberOfLife Aug 24 '16 at 15:17
  • 1
    You're right in thinking that [exceptions aren't entirely appropriate to control flow](http://programmers.stackexchange.com/questions/189222/are-exceptions-as-control-flow-considered-a-serious-antipattern-if-so-why) like this. But really, the most correct way to do this is to just return something from `ExitMethod` and wrap the call with an `if(..) return;` – James Thorpe Aug 24 '16 at 15:23
  • 1
    To be fair, your possible application ("By using another method that can be called for the cancellation task I want to avoid something like...") describes *what* you want to do, but not *why* you want to do it. There is no obvious reason why someone would want to call a method to exit a method instead of using a common IF statement. If we knew why you wanted to avoid the IF statement, we might be able to provide you with a better solution. – DeadZone Aug 24 '16 at 15:23
  • Did you read the question? There is an example application given. Quote: "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." – RememberOfLife Aug 24 '16 at 15:27
  • 1
    You're obviously getting frustrated. So I'll try one more time to rephrase my question... _Why are you trying to avoid the IF statement?_ It seems to me that you can accomplish your need to validate a serial key and exit by using IF and not need to jump through these hoops. So why try so hard to avoid the IF? If that question still does not make sense to you, I apologize. – DeadZone Aug 24 '16 at 15:36
  • It's ok I am not trying to hard avoid the if. To understand the context I am lazy and I like to have things optimized to where there can not be optimized further so I have to do less. By avoiding the if it is less work to implement that somewhere. I am totally ok with the exception as an answer. I just asked this question to see if someone knows how this can be optimized because 'obviously' I do not. ;D Shall I answer it with the exception thingy from myself or what else? – RememberOfLife Aug 24 '16 at 15:39
  • If you avoid the `if` by throwing an exception, you'll just need to add an exception handler somewhere else instead. Just use the `if`. – James Thorpe Aug 24 '16 at 15:41
  • Good idea actually. – RememberOfLife Aug 24 '16 at 15:42

1 Answers1

5

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");
}
Jonathan Dickinson
  • 9,050
  • 1
  • 37
  • 60
  • You have some really interesting things there, but yes judging from what I know and the comment this is a really solid solution(s). Just note that the exception can be handled without a try. – RememberOfLife Aug 24 '16 at 15:47