Return Tuple <bool, string> instead of throwing exception ()?

I have a Foo () method that does some hard work, and at the user interface level, I have a button to call this method.
All I want to do is call the method and show a message if something is wrong with the Foo () method.

I have two options for developing a method signature:

1.Tuple

Tuple<bool, string> Foo() { if(!DoHardWorkA()) return Tuple.New(false, "cannot do hardwork A"); if(!DoHardWorkB()) return Tuple.New(false, "cannot do hardwork B"); return Tuple.New(true, String.Empty); } 

2.Exception

 void Foo() { if(!DoHardWorkA()) throw new ProgramSpecificException("cannot do hardwork A"); if(!DoHardWorkB()) throw new ProgramSpecificException("cannot do hardwork B"); return Tuple.New(true, String.Empty); } 

Both DoHardWorkA () and DoHardWorkB () are external methods in which I do not control them, and they return true / false indicating the result.

Logically, I think I should go with option 2, as they really are exceptions; But for consistency, I would like to go with option 1.

Which one do you prefer, why?

+4
source share
5 answers

Throw an exception and handle it in a consistent manner.

If Foo crashes for any other reason, then it will also be processed. Suppose sceneio.

 void UIMethod() { Tuple<Result, Error> ret = Foo(); if(ret.Error) MessageBox.Show(ret.Error); } 

Now, due to a change in the requirement, you must call another method before Foo, and it can also throw an exception. Then it becomes complicated.

It is much easier to do.

 void UIMethod() { try{ MethodBeforeFoo(); var ret = Foo(); } catch(Exception ex) { MessageBox.Show(ex.Message); } } 
+3
source

It really depends on your need. Change your code in this way, it will also handle unhandled exceptions.

  Tuple<bool, string> Foo() { try { if(!DoHardWorkA()) return Tuple.New(false, "cannot do hardwork A"); if(!DoHardWorkB()) return Tuple.New(false, "cannot do hardwork B"); return Tuple.New(true, String.Empty); } catch { return Tuple.New(false, "cannot do hardwork A"); } 

}

+1
source

If all you do is call these external methods to do some work, and this method you write is a wrapper around them, then why throw an exception, "handle" the problem in your method and continue throwing and handling exceptions - it's many many times more expensive

In your particular case, everything you do does some work and displays a message box to show if it is executed correctly, so I would go with option 1

Please note that if you just catch the exception and don't unwind the stack, the cost is pretty minimal. It is only expensive when you unwind a stack like ex.ToString() or ex.StackTrace

+1
source

What I once did was returning null on success or an error message on failure. An exception was inappropriate, as failure was probable, and other developers like to work with Break with exception exceptions.

 String Foo() { if(!DoHardWorkA()) return "cannot do hardwork A"; if(!DoHardWorkB()) return "cannot do hardwork B"; return null; } 
0
source

Using exceptions has advnatage, which you can potentially (*) distinguish from the cause more easily than the suggested return value of the tuple. To find out which thing is to blame for using a tuple, you must interpret a string value that is error prone. Using exceptions, you can determine the type of error based on the type of exception.

(*) depends on how the exceptions are used - if you throw a general exception all the time, it will not differ

Of course, you can use an integer in a tuple to indicate the type of problem, but the numerical value for the type of error is not as descriptive as the type of exception (again, if you are not using a generic type, such as Exception).

0
source

Source: https://habr.com/ru/post/1402714/


All Articles