Using exceptions for error handling flow? - c#

I have the following pattern:
private void MyFunction()
{
doStuff();
if (problem())
{
cleanup();
return;
}
doMoreStuff();
if (otherProblem())
{
cleanup();
return;
}
doYetMoreStuff();
}
The error cleanup code is duplicated. The obvious way to eliminate this is:
private void MyFunction()
{
try {
doStuff();
if (problem()) throw new MyException();
doMoreStuff();
if (otherProblem()) throw new MyException();
doYetMoreStuff();
}
catch (MyException)
{
cleanup();
return;
}
}
However, the error cases are not really exceptional - this is an ASP.Net page, and bad or no data in the query string will trigger the error cases. Exceptions seem to be the most obvious way to deduplicate the error handling and separate it from the main code, but as I understand it the accepted best practice is not to use exceptions for control flow like this.
What is the customary way of doing this?

Using exceptions for non-exceptional situations is not a great idea, especially when the exception is thrown and caught in the same method. A better approach would be to use a boolean variable that indicates a need for cleanup, and performing your cleanup inside a finally block.
var needsCleanup = true;
try {
doStuff();
if (problem()) return;
doMoreStuff();
if (otherProblem()) return;
doYetMoreStuff();
needsCleanup = false;
} finally {
if (needsCleanup) {
cleanup;
}
}

You could use just try .. finally and early returns.
private void MyFunction()
{
try
{
doStuff();
if (problem())
{
return;
}
doMoreStuff();
if (otherProblem())
{
return;
}
doYetMoreStuff();
}
finally
{
cleanup();
}
}

The finally block will be executed any time execution leaves the try block, even if the reason that it leaves the try block is because you call return. So, you could do something like this:
private void MyFunction()
{
try
{
doStuff();
if (problem()) return;
doMoreStuff();
if (otherProblem()) return;
doYetMoreStuff();
}
finally
{
cleanup();
}
}

If cleanup() is really just a method call than it's not duplicated.
I wouldn't use exceptions in this case.
You can easily google for articles describing in details why using exception in normal flow is a bad idea: mainly in impacts performance and can screw up performance counters ('# of exceptions thrown' will be meaningless).

Exceptions should be thrown when something unexpected happens.
Consider that you want to add a user in your database, but if the username already exists, you just want a error saying so. Now, an error does not have to be an exception!
bool AddUser(string username)
Now the flow would look like this instead:
if(AddUser(username)) {}
else
{
// Notify the user that it didn't work
}
If an exception was thrown here, it Should be because the software couldn't connect to the database, not because the username already existed.
throwing and catching exceptions for flow control like this will cause more overhead than needed and thus you should use if/else to control this instead.

Related

Disable breaking code execution on exception

If i will write something like this:
void Code()
{
Console.WriteLine("a");
throw new Exception(); //the code will stop executing here
Console.WriteLine("b");
}
the code will stop executing after writing "a" to console. I am wondering, is it possible to execute whole function and then throw an exception? So if the exception will be thrown between Console.WriteLine("a"); and Console.WriteLine("b");, it will stop code execution, but i want the function to be executed fully before throwing an exception
Not really suggested at all, but i guess you could do something like this.
var errors = new List < Exception > ();
Console.WriteLine("a");
try {
ErrorThrowingMethod();
} catch (Exception e) {
errors.Add(e);
}
Console.WriteLine("b");
if (errors.Any()) throw new AggregateException(errors);
Simply put: No, you cant.
And shouldn't try to bend the programming logics to that way either.
An exception is the indication that something went terribly wrong and the function has to quit without a return value. That is the purpose of the exception, to indicate there was an error running the function and it COULDN'T COMPLETE execution.
void Code()
{
Boolean anyErrors = false;
Console.WriteLine("a");
anyErrors = true; // whenever something goes wrong.
Console.WriteLine("b");
if(anyErrors)
throw new Exception("There were errors doing whatever I was trying to.");
}
You can also in this case:
// will return false if it fails and true if succeeds.
Boolean Code()
{
Boolean anyErrors = false;
Console.WriteLine("a");
anyErrors = true; // whenever something goes wrong.
Console.WriteLine("b");
return !anyErrors;
}
Logics is the basis of programming, think logical and you won't have to fight the language.
You can do
void Code()
{
try
{
Console.WriteLine("a");
throw new Exception(); //the code will stop executing here
Console.WriteLine("b");
}
catch(Exception e)
{
Console.WriteLine("b");
throw new Exception(e.toString());
}
}
which will do what I think you are trying to achieve in this specific case, but as mentioned, often times it just doesn't make sense to try to continue because of dependency on events beforehand.

Throw exception with method by given parameter C#

I want to make a method, that throws a specific exception, by a parameter I give to the method. I have 3 userdefined exceptions, so instead of having to throw them every time I want to use them I want to make a method that handels it, so the parameter I give with my method is the exception I want to throw, but how do I do that?
I want to do something like this, but I am not really sure how to do it.
private void ExceptionMethod(custom exception)
{
try
{
//code that might fail
}
catch(exception ex)
{
throw new exception given by parameter(parameters from the exception);
}
}
FWIW I don't think this is a particulary good idea. Really, just throw your exception where it occurs, future maintainers of the code will thank you. (or at least not curse you)
If you have to do this thing, then its probably a better idea to pass an enumeration that you can switch on rather than the exception itself, then simply write a case statement to throw the exception you want.
Apart from the fact that this sounds like a bad idea, you can try the following:
private void TryElseThrow<TCustomException>(Action codeThatMightFail)
where TCustomException : Exception
{
try
{
codeThatMightFail();
}
catch (Exception e)
{
// Since there isn't a generic type constraint for a constructor
// that expects a specific parameter, we'll have to risk it :-)
throw
(TCustomException)Activator
.CreateInstance(typeof(TCustomException), e);
}
}
Use like so:
TryElseThrow<MyCustomException>(
() =>
{
throw new InvalidOperationException();
}
);
You were actually quite close:
private void ExceptionMethod(Exception customException)
{
try
{
//code that might fail
}
catch(Exception ex)
{
throw customException;
}
}
Will work, though I wouldn't recommend it for two reasons:
Catching Exception is a bad idea - you should just catch the exceptions that your code raises.
It's not a very good design (as others have pointed out).
So i dont see any problem in that.. as you say you already have your Custom Exception Written then you can do it like this.
in your parameter:
private void ExceptionMethod(CustomException myexception)
in catch:
throw myexception;
though its not a good Coding Design
Wouldn't it just be:
private void ExceptionMethod(MyCustomException exception)
{
try
{
//code that might fail
}
catch
{
throw exception;
}
}

C#: Equivalent of the python try/catch/else block

In Python, there is this useful exception handling code:
try:
# Code that could raise an exception
except Exception:
# Exception handling
else:
# Code to execute if the try block DID NOT fail
I think it's useful to be able to separate the code that could raise and exception from your normal code. In Python, this was possible as shown above, however I can't find anything like it in C#.
Assuming the feature or one like it doesn't exist, is it standard practice to put normal code in the try block or after the catch block?
The reason I ask is because I have the following code:
if (!IsReadOnly)
{
T newobj;
try
{
newobj = DataPortal.Update<T>(this);
List<string> keys = new List<string>(BasicProperties.Keys);
foreach (string key in keys)
{
BasicProperties[key] = newobj.BasicProperties[key];
}
}
catch (DataPortalException)
{
// TODO: Implement DataPortal.Update<T>() recovery mechanism
}
}
Which requires the normal code to be in the try block because otherwise if an exception was raised and subsequently handled, newobj would be unassigned, but it feels quite unnatural to have this much code in the try block which is unrelated to the DataPortalException. What to do?
Thanks
I would prefer to see the rest of the code outside the try/catch so it is clear where the exception you are trying to catch is coming from and that you don't accidentally catch an exception that you weren't trying to catch.
I think the closest equivalent to the Python try/catch/else is to use a local boolean variable to remember whether or not an exception was thrown.
bool success;
try
{
foo();
success = true;
}
catch (MyException)
{
recover();
success = false;
}
if (success)
{
bar();
}
But if you are doing this, I'd ask why you don't either fully recover from the exception so that you can continue as if there had been success, or else fully abort by returning an error code or even just letting the exception propagate to the caller.
Barbaric solution: create an Else class derived from Exception, throw an instance of it at the end of the try block, and use catch (Else) {...} to handle the other stuff.
I feel so dirty.
This will might get downvoted but doesn't c# have goto(note I have almost no c# knowledge so I have no idea if this works).
what about something like
try
{
...
}
catch(Exception ex)
{
...
goto Jump_past_tryelse
}
...//Code to execute if the try block DID NOT fail
Jump_past_tryelse:
...
C# does not have such a concept, so you are just left with three options,
put the else code inside the try.
put the else code outside the try catch block, use a local variable to indicate success or failure, and an if block around your else code.
put the else code in the finally block, use a local variable to indicate success or failure, and an if block arount you else code.
Allow me to repeat an idea from a similar StackOverflow question. You cannot do this directly, but you can write a method that encapsulates the behavior you need. Look at the original question to see how to implement the method (if you're not familiar with lambda expressions and Func delegates). The usage could look like this:
TryExceptRaise(() => {
// code that can throw exception
}, (Exception e) => {
// code to run in case of an exception
return (...);
}, () => {
// code to run if there is no exception
return (...);
});
Just put your "else" block before the catch. Then, it will only execute if code execution reaches that point:
try
{
fee();
fi();
foe();
fum();
/// put your "else" stuff here.
/// It will only be executed if fee-fi-foe-fum did not fail.
}
catch(Exception e)
{
// handle exception
}
Given that, I fail to see the use of try..catch...else unless there's something vital missing from the OP's description.
With C# version 7, you could use local functions to emulate this behaviour:
Example 1: (since C# version 7)
void Main()
{
void checkedCode()
{
try
{
foo();
}
catch (Exception ex)
{
recover();
return;
}
// ElseCode here
}
checkedCode();
}
If you prefer lambda syntax, you could also declare a run method
void Run(Action r) { r(); }
which only needs to be there once in your code, and then use the pattern for anonymous methods as follows
Example 2: (older C# versions and C# version 7)
Run(() => {
try
{
foo();
}
catch (Exception)
{
recover();
return;
}
// ElseCode here
});
whereever you need to enclose code in a safe context.
Try it in DotNetFiddle
Notes:
In both examples a function context is created so that we can use return; to exit on error.
You can find a similar pattern like the one used in Example 2 in JavaScript: Self-invoking anonymous functions (e.g. JQuery uses them). Because in C# you cannot self-invoke, the helper method Run is used.
Since Run does not have to be a local function, Example 2 works with older C# versions as well
You could do something like this:
if (!IsReadOnly)
{
T newobj = null;
try
{
newobj = DataPortal.Update<T>(this);
}
catch (DataPortalException)
{
// TODO: Implement DataPortal.Update<T>() recovery mechanism
}
if (newobj != null)
{
List<string> keys = new List<string>(BasicProperties.Keys);
foreach (string key in keys)
{
BasicProperties[key] = newobj.BasicProperties[key];
}
}
}
that would be the empty statement like hits
try
{
somethingThatCanThrow();
}
catch(Exception ex)
{
LogException(ex);
return;
}
ContinueFlow();
if (!IsReadOnly)
{
T newobj;
bool Done;
try
{
newobj = DataPortal.Update<T>(this);
List<string> keys = new List<string>(BasicProperties.Keys);
foreach (string key in keys)
{
BasicProperties[key] = newobj.BasicProperties[key];
}
Done = true;
}
catch (DataPortalException)
{
// TODO: Implement DataPortal.Update<T>() recovery mechanism
Done = false;
}
finally
{
if (newobj != null && Done == false)
{
List<string> keys = new List<string>(BasicProperties.Keys);
foreach (string key in keys)
{
BasicProperties[key] = newobj.BasicProperties[key];
}
}
}
}

C# Should I Loop until no exception?

I want to go once through a loop but only if an exception is thrown go back through the loop. How would I write this in C#?
Thanks
This smells of bad design to me. The general rule is: exceptions should not be used for flow control. There are a number of reasons for this; namely, there are usually better/more reliable methods that can be used to check things before an exceptions is thrown, and also it decreases efficiency.
Nonetheless, just for the sake of argument, you could do something like the following:
while (true)
{
try
{
// do stuff here
}
catch (MyException)
{
continue;
}
// all is good
break;
}
Again - this is not the recommended way. I would be happy to suggest something better if you could provide a bit more context/examples/
What about the following where you can set a retry count:
int tryCount = 0;
while (tryCount < 3)
{
try
{
someReturn = SomeFunction(someParams);
}
catch (Exception)
{
tryCount++;
continue;
}
break;
}
That really depends on what you're doing, and the type of exception being thrown. Many exceptions aren't something that would be fixed by just trying again with the exact same inputs/data, and thus looping would just keep generating the exception ad infinitum.
Instead, you should check for relevant exceptions and then handle them in an appropriate manner for those particular exceptions.
You could use Polly
and then you just need to configure the Policy with your exceptions and retry count:
var retryPolicy = Policy
.Handle<IOException>(x => x.Message.Contains("already exist"))
.Or<FormatException>()
.Retry(3);
and you use like this:
retryPolicy.Execute(() =>
{
throw new FormatException();
});
Why not call a function that actually does the loop, and have a catch after it that would call the function again.
private void loop() {
for(...) {
}
}
some other method:
try {
loop();
} catch(Exception e) {
loop();
}
Something like:
bool done = false;
while( ! done )
{
try
{
DoSomething();
done = true;
} catch(Exception ex)
{
HandleException(ex);
}
}
As Noldorin said, it smells like a bad design. You're using exceptions to control the flow of the program. Better to have explicit checks for the conditions that will cause you to repeat the operation.
So I am using this simple stuff :D
bool exceptionthrow = false;
while (!exceptionthrow)
{
try
{
value = Convert.ToInt32(Console.ReadLine()); //example
exceptionthrow = true;
}
catch (Exception)
{
exceptionthrow = false;
continue;
}
}
Hope it helps :)

What is the best way to execute sequential methods?

Working on a project where a sequential set of methods must be run every x seconds. Right now I have the methods contained within another "parent method", and just sequentially call them right after another.
class DoTheseThings()
{
DoThis();
NowDoThat();
NowDoThis();
MoreWork();
AndImSpent();
}
Each method must run successfully without throwing an exception before the next step can be done. So now I wrapped each of those methods with a while and try..catch, then in the catch execute that method again.
while( !hadError )
{
try
{
DoThis();
}
catch(Exception doThisException )
{
hadError = true;
}
}
This seems smelly and not very dry. Is there a better way to do this so I'm not wrapping any new functionality in the same methods. Isn't some kind of Delegate collection the proper way to implement this?
Is there a more "proper" solution?
Action[] work=new Action[]{new Action(DoThis), new Action(NowDoThat),
new Action(NowDoThis), new Action(MoreWork), new Action(AndImSpent)};
int current =0;
while(current!=work.Length)
{
try
{
work[current]();
current++;
}
catch(Exception ex)
{
// log the error or whatever
// maybe sleep a while to not kill the processors if a successful execution depends on time elapsed
}
}
Isn't some kind of Delegate collection the proper way to implement this?
Delegate is a possible way to solve this problem.
Just create a delegate something like:
public delegate void WorkDelegate();
and put them in arraylist which you can iterate over.
I have a personal religious belief that you shouldn't catch System.Exception, or more accurately, you should only catch the exceptions you know how to handle.
That being said, I am going to assume that each one of the methods that you are calling are doing something different, and could result in different exceptions being thrown. Which means you would likely need to have different handlers for each method.
If you follow my religion as well, and the second statement is true, then you are not repeating code unnecessarily. Unless you have other requirements, my recommendations to improve your code would be:
1) Put the try-catch in each method, not around each method call.
2) Have the catches within each method catch ONLY the exceptions you know about.
http://blogs.msdn.com/fxcop/archive/2006/06/14/631923.aspx
http://blogs.msdn.com/oldnewthing/archive/2005/01/14/352949.aspx
http://www.joelonsoftware.com/articles/Wrong.html
HTH ...
your example seems ok.. its a dry one but will do the job well!! actually if this methods execute db access.. you can use transaction to ensure integrity...
if your dealing with shared variables for multi threader programs.. it is cleaner to use synchronization.. the most important thing in coding is that you write the proper code... that has less bugs.. and will do the task correctly..
public void DoTheseThings()
{
SafelyDoEach( new Action[]{
DoThis,
NowDoThat,
NowDoThis,
MoreWork,
AndImSpent
})
}
public void SafelyDoEach( params Action[] actions )
{
try
{
foreach( var a in actions )
a();
}
catch( Exception doThisException )
{
// blindly swallowing every exception like this is a terrible idea
// you should really only be swallowing a specific MyAbortedException type
return;
}
}
What would be the reason that an error was occuring?
If this were a resource issue, such as access to something like a connection or object, then you might want to look at using monitors, semaphores, or just locking.
lock (resource)
{
Dosomething(resource);
}
This way if a previous method is accessing the resource, then you can wait until it releases the resource to continue.
Ideally, you shouldn't have to run a loop to execute something each time it fails. It is failing at all, you would want to know about the issue and fix it. Having a loop to always just keep trying is not the right way to go here.
I'd do what Ovidiu Pacurar suggests, only I'd use a foreach loop and leave dealing with array indexes up to the compiler.
Simple delegate approach:
Action<Action> tryForever = (action) => {
bool success;
do {
try {
action();
success = true;
} catch (Exception) {
// should probably log or something here...
}
} while (!success);
};
void DoEverything() {
tryForever(DoThis);
tryForever(NowDoThat);
tryForever(NowDoThis);
tryForever(MoreWork);
tryForever(AndImSpent);
}
Stack approach:
void DoEverything() {
Stack<Action> thingsToDo = new Stack<Action>(
new Action[] {
DoThis, NowDoThat, NowDoThis, MoreWork, AndImSpent
}
);
Action action;
while ((action = thingsToDo.Pop()) != null) {
bool success;
do {
try {
action();
success = true;
} catch (Exception) {
}
} while (!success);
}

Categories