I'm looking for the best method of handling errors in a c# winforms class that I have. The gist of the application is that it has a data analyzer that analyzes the data for statistics and other such stuff. However, I'm looking for the proper way of handling an ABORT.
For example, I have the class called Analyzer
namespace PHOEBE
{
public class Analyzer
{
public Analyzer(){
DoAnalysis();
DoFurtherAnalysis();
}
public class DoAnalysis(){
try{
Convert.ToInt32("someNumber...."); //obviously fails..
}
catch{
//ERROR OCCURRED, ABORT ALL ANALYSIS
return;
}
}
}
Obviously, when DoAnalysis() is called, there will be an error that occurs. The catch block will catch the exception. However, when this catch occurs, it will return to the constructor and run DoFurtherAnalysis(). This is a problem.
I know that you could do return values from each method where each value indicates a certain outcome (ie. 1 = success, 0 = fail). However, a lot of the methods I call, use return values already. I could also use a boolean that gets flagged when an error occurs and check that value before calling the next method from the constructor, but checking this value each time is annoying and repetitive.
I was really hoping for some sort of like "abort mechanism" that I could use. Is there any other ways of working around this? Any interesting work-arounds for this?
Assume this class is being called from a form.
Just let the exception propagate up - you should only catch the exception if you can actually handle it. Exceptions are the "abort mechanism" in .NET. You're currently swallowing the signal that everything's gone wrong, and returning as if all were well.
Generally I find catching exceptions to be pretty rare - usually it's either at the top level (to stop a whole server from going down just because of one request) or in order to transform an exception of one kind into another in order to maintain appropriate abstractions.
I was really hoping for some sort of like "abort mechanism" that I
could use. Is there any other ways of working around this? Any
interesting work-arounds for this?
Yes, there is. It is called exception handling.
Let's rewrite your code:
namespace PHOEBE
{
public class Analyzer
{
public Analyzer()
{
try
{
DoAnalysis();
DoFurtherAnalysis();
}
catch
{
//ERROR OCCURRED, ABORT ALL ANALYSIS
return;
}
}
public class DoAnalysis()
{
Convert.ToInt32("someNumber...."); //obviously fails..
}
}
Now, the constructor will abort and not run the second method since the exception will "bubble through" and be catched where you want it.
On an unrelated note: Please try to catch as specific exceptions as possible, in this case a FormatException
You are subverting the existing "abort" mechanism by catching an exception that you are not doing anything about and swallowing it.
You should not use a try{}catch{} block in this case and let the exception bubble up and cause the application to abort.
The easiest work-around is don't catch the exception. If that were to happen, it'd go straight past the DoFurtherAnalysis() function and out to the original caller.
Don't see anything anoying in returning and checking bool return value from the function. It's much much better solution then having some tricky internal state management, that you for sure will messed up after a couple of months when you return to your code.
Make code sumple and streghtforward. It's not anoying, it's good.
In your specific case if you want just abort everything, just do not catch exception it will abort your program.
use a try...catch in the constructor?
Well, you've got several issues mixed up here. First, it looks like you do possibly-very expensive processing from your constructor. If that processing can throw, you really don't want to call it from your constructor becuase you don't even have the option of returning an error code.
Second, (and you'll read in many threads here,) how you handlee errors really depends on the application and expectation of your users. Some errors could be corrected by changes to inputs. Others might happen in the middle of the night if analysis takes a long time and you might want to continue with another analysis, logging this error.
So I think we're really going to punt back to you for more information about the above.
You could just move DoFurtherAnalysis(); into the the try block
And I would do this entire process somewhere other than the constructor.
Only thing I ever do in the constructor is initialize properties.
Related
I sometimes run into situations where I need to catch an exception if it's ever thrown but never do anything with it. In other words, an exception could occur but it doesn't matter if it does.
I recently read this article about a similar thing: http://c2.com/cgi/wiki?EmptyCatchClause
This person talks about how the comment of
// should never occur
is a code smell and should never appear in code. They then go onto explain how the comment
// don't care if it happens
is entirely different and I run into situations like this myself. For example, when sending email I do something similar to this:
var addressCollection = new MailAddressCollection();
foreach (string address in addresses)
{
try
{
addressCollection.Add(address);
}
catch (Exception)
{
// Do nothing - if an invalid email occurs continue and try to add the rest
}
}
Now, you may think that doing this is a bad idea since you would want to return to the user and explain that one or more messages could not be sent to the recipient. But what if it's just a CC address? That's less important and you may still want to send the message anyway even if one of those addresses was invalid (possibly just a typo).
So am I right to use an empty catch block or is there a better alternative that I'm not aware of?
You are completely right to use an empty catch block if you really want to do nothing when a certain type of exception occurs. You could improve your example by catching only the types of exceptions which you expect to occur, and which you know are safe to ignore. By catching Exception, you could hide bugs and make it harder for yourself to debug your program.
One thing to bear in mind regarding exception handling: there is a big difference between exceptions which are used to signal an error condition external to your program, which is expected to happen at least sometimes, and exceptions which indicate a programming error. An example of the 1st would be an exception indicating that an e-mail couldn't be delivered because the connection timed out, or a file couldn't be saved because there was no disk space. An example of the 2nd would be an exception indicating that you tried to pass the wrong type of argument to a method, or that you tried to access an array element out of bounds.
For the 2nd (programming error), it would be a big mistake to just "swallow" the exception. The best thing to do is usually to log a stack trace, and then pop up an error message telling the user that an internal error has happened, and that they should send their logs back to the developers (i.e. you). Or while developing, you might just make it print a stack trace to the console and crash the program.
For the 1st (external problem), there is no rule about what the "right" thing is to do. It all depends on the details of the application. If you want to ignore a certain condition and continue, then do so.
IN GENERAL:
It's good that you are reading technical books and articles. You can learn a lot from doing so. But please remember, as you read, you will find lots of advice from people saying that doing such-and-such a thing is always wrong or always right. Often these opinions border on religion. NEVER believe that doing things a certain way is absolutely "right" because a book or article (or an answer on SO... <cough>) told you so. There are exceptions to every rule, and the people writing those articles don't know the details of your application. You do. Make sure that what you are reading makes sense, and if it doesn't, trust yourself.
An empty catch block is fine in the right place - though from your sample I would say you should cetagorically NOT be using catch (Exception). You should instead catch the explicit exception that you expect to occur.
The reason for this is that, if you swallow everything, you will swallow critical defects that you weren't expecting, too. There's a world of difference between "I can't send to this email address" and "your computer is out of disk space." You don't want to keep trying to send the next 10000 emails if you're out of disk space!
The difference between "should not happen" and "don't care if it happens" is that, if it "should not happen" then, when it does happen, you don't want to swallow it silently! If it's a condition you never expected to occur, you would typically want your application to crash (or at least terminate cleanly and log profusely what's happened) so that you can identify this impossible condition.
If an exception should never be thrown then there is no point catching it - it should never happens and if it does you need to know about it.
If there are specific scenarios that can cause a failure that you are OK with then you should catch and test for those specific scenarios and rethrow in all other cases, for example
foreach (string address in addresses)
{
try
{
addressCollection.Add(address);
}
catch (EmailNotSentException ex)
{
if (IsCausedByMissingCcAddress(ex))
{
// Handle this case here e.g. display a warning or just nothing
}
else
{
throw;
}
}
}
Note that the above code catches specific (if fictional) exceptions rather than catching Exception. I can think of very few cases where it is legitimate to catch Exception as opposed to catching some specific exception type that you are expecting to be thrown.
Many of the other answers give good reasons when it would be ok to catch the exception, however many classes support ways of not throwing the Exception at all.
Often these methods will have the prefix Try in front of them. Instead of throwing a exception the function returns a Boolean indicating if the task succeeded.
A good example of this is Parse vs TryParse
string s = "Potato";
int i;
if(int.TryParse(s, out i))
{
//This code is only executed if "s" was parsed succesfully.
aCollectionOfInts.Add(i);
}
If you try the above function in a loop and compare it with its Parse + Catch equilvilant the TryParse method will be much faster.
Using an empty catch block just swallows the Exception, I would always handle it, even if it is reporting back to you that an Exception occurred.
Also catching the generic Exception is bad practice due to the fact it can hide bugs in your application. For example, you may have caught an ArgumentOutOfRange exception which you did not realize was happening and then swallowed it (I.e. not done anything with it).
So I am recently writing a relatively complex application written in C# that performs an array of small tasks repeatedly. When I first started the application I realized that a lot of the code I was typing was repetitive and so I began encapsulating the majority of the app's logic into separate helper classes that I could call as needed.
Needless to say the size of my app (and amount of code) was cut in half. But as I was going through I noticed something else in my application that seemed to be repetitive and looked like it could be improved.
Now most of my methods in my helper classes are either making a HttpWebRequest or performing save/delete operations on files. Having said that I need to handle the possibility that eventually the call won't complete, or the file can't save because there isn't enough space, or whatever. The problem I'm running into is that I have to keep writing try/catch statements every time I call one of the methods. On top of that I have to retype the error message (or Eventually a status message. I would like to know when it succeeds as well).
So here's kind of a snippet of what I have to type:
try
{
ItemManager.SaveTextPost(myPostItem);
}
// Majority of the time there is more than one catch!
catch
{
//^^^Not to mention that I have to handle multiple types of exceptions
//in order to log them correctly(more catches..ugh!)
MessageBox.Show("There was an error saving the post.");
//Perform logging here as well
}
From what I have concluded so far is:
To me this is overkill having to write this over 50 times for my app.
Sounds like I should be including this in the helper class and
include the full set of catches.
But how could I know the result? I was maybe thinking of returning a
string that contains the error/success message.
Really for these types of methods it doesn't require the method from which the helper method is being called from to enclose it in a try/catch block.
Is this approach correct? Is there another way of doing this? Should I be using a try/catch in the calling method at all? Since this kind of my first shot at this I would really like to hear what others who have handled this scenario have to say.
I think putting the try/catch in the method you are calling is perfectly fine. You can return error/success codes to the calling code in a variety of ways. .NET and c# handle enumerations nicely, so you could have ItemManager.SaveTextPost(myPostItem, out errorCode); where errorCode would be an enumerated value that would let you know if any problems occurred. It could also be as simple as having the method return a bool true if successful, false if otherwise. There are many ways that you could handle that issue, but as far as I'm concerned putting the try/catch in the method is the preferable way of doing things.
AOP libraries like PostSharp are designed to handle cross-cutting concerns exactly like this.
If all these helper methods employ the same boilerplate try catch -> handle multiple types of exceptions, then you can write one aspect that does that, and decorate all of the relevant methods with the appropriate attribute.
There is no single perfect rule for exception handling, so the answer is: It depends. In general you should only catch exceptions, if you know how to handle them. In your example my first question would be, if the application can continue to run after this error and would still be in a valid state. If not, you should rethrow the exception after logging. Then think about nesting exception: You can catch an exception, add information by nesting it into another and throwing that exception. If you design your exception classes and handlers carefully, your logging and displaying code should become much simpler than you expect it. But the details obviously depend on your application.
All of these ways are great options. One thing you want not to do is to use a try {} catch {} for flow control. This means something like this (again avoid this)
Void SomeMethod()
{
try
{
while(somecondition)
{
try
{
}
catch (Exception ex)
{
}
}
}
catch (Exception ex)
{
.....
}
Instead you want to code defensively.
You should throw exceptions in your helper methods by checking with if blocks if every argument is correct, every file is reachable... then if needed, implement some try catch blocks in your helper methods and throw exceptions when catching.
Finally, enclose these helper methods by a try catch block, but at this time, really catch the exceptions:
try
{
ItemManager.SaveTextPost(myPostItem);
// SaveTextPost can throw some exceptions (that you know)
}
catch (Exception e)
{
// You know the exceptions that SaveTextPost can return, so threat them
// correctly
if (e is FileNotFoundException)
MessageBox.Show("The file was not found when saving the post.");
else if (e is ArgumentNullException)
MessageBox.Show("The post can't be null to be saved.");
else
MessageBox.Show("There was an error saving the post.");
}
At the end, you need to treat the error and show an error message to the user. You only can decide if the MessageBox.Show should be implemented in the helper method or in the class calling the helper method.
Personally, I think helper methods are destined to be used by any developer that will run your code, so you should let him decide what he wants to do with the error. That means throwing exceptions in the helper method.
Try/Catch is a good solution. One suggestion, I like to use this to stem the flow of errors: exception catching:
try
{
}
catch (Exception ex)
{
ShowExceptionError(ex);
}
Then I will simply throw all exceptions to a single method, and let the method handle each.
Kind of like this:
private void ShowExceptionError(ex)
{
string errorMessage = "Type of error:" + ex.GetType().ToString();
string stackTrace = ex.StackTrace();
MessageBox.Show(errorMessage + "\n\n" + stackTrace);
}
My personal take on exception handling is.. add try {} catch {} where it makes sense.
For example always use a try catch when calling "untrusted" code, i.e. modules or plugins. otherwise if you are going to catch an exception make sure you can do something meaningful with it. If not, allow the exception to bubble up to a point where you can.
There are few things worse than trying to debug an app where the developer caught an exception and returns a bool. Just sayin'
I get the feeling that this is, but I wanted to confirm-
is it bad form to do something like:
try
{
SqlUpload(table);
}
catch(PrimaryKeyException pke)
{
DeleteDuplicatesInTable(table);
SqlUpload(table);
}
catch(Exception ex)
{
Console.Write(ex);
}
Is it better to do this to potentially save on efficiency in case the table doesn't have duplicates, or is it better to run the delete duplicates bit anyway? (I'm assuming conditions where the table will upload as long as there are no duplicates within the table itself). Also, given how try-catch statements impact performance, would it even be faster to do it this way at all?
I apologize for the crude nature of this example, but it was just to illustrate a point.
Exceptions can be used correctly in transaction management, but it is not the case in this example. On my first look, it appeared that this seemed similar to what Linq2Sql's DataContext class does in its call to SubmitChanges(). However, that analogy was incorrect. (Please see at Chris Marisic's comment to my post for an accurate criticism of the comparison).
On exceptions
In general, if there is some issue that is likely to be encountered, you should check for it first. Exceptions should be used when a response is truly "exceptional" (meaning it is unexpected in the context of proper usage). If the proper usage of a function within a completely valid context throws an exception , then you are probably using exceptions incorrectly.
Excerpt from DataContext.SubmitChanges
This code shows an example of the correct usage of exceptions in transaction management.
Note: Just because Microsoft does it, doesn't automatically mean its right. However, their code does have a pretty good track record.
DbTransaction transaction = null;
try
{
try
{
if (this.provider.Connection.State == ConnectionState.Open)
{
this.provider.ClearConnection();
}
if (this.provider.Connection.State == ConnectionState.Closed)
{
this.provider.Connection.Open();
flag = true;
}
transaction = this.provider.Connection.BeginTransaction(IsolationLevel.ReadCommitted);
this.provider.Transaction = transaction;
new ChangeProcessor(this.services, this).SubmitChanges(failureMode);
this.AcceptChanges();
this.provider.ClearConnection();
transaction.Commit();
}
catch
{
if (transaction != null)
{
try
{
transaction.Rollback();
}
catch
{
}
}
throw;
}
return;
}
finally
{
this.provider.Transaction = null;
if (flag)
{
this.provider.Connection.Close();
}
}
}
Yes, this type of code is considered bad form in .NET.
You would be better off writing either code similar to
if(HasPrimaryKeyViolations(table))
DeletePrimaryKeyViolations(table)
SqlUpload(table)
By reading this code I would assume that primary key violations are an exceptional case and not expected - if they are I think you should remove the duplicates beforehand, do not rely on exception handling for an expected case.
In all common languages/interpreters/compilers, exception handling is implemented to have a minimal performance impact when an exception isn't raised -- under the hood, adding an exception handler is usually just pushing a single value onto a stack or something similar. Just adding a try block wont usually have a performance impact.
On the other hand, when an exception is actually raised, things can get very slow very fast. Its the trade-off for being able to add the try block without worrying about worrying, and its usually seen as acceptable, because you only take the performance hit if something unexpected has already gone wrong somewhere else.
So, in theory, if there is a condition that you expect to happen, use an if instead. Its semantically better because it expresses to the reader that the bad condition is probably going to happen from time to time (e.g., user types in some invalid input), while the try expresses something that you hope never happens (the data source is corrupt). As above, its also going to be easier on performance.
Of course, rules are defined by their exceptions (no pun intended). In practice, there are two situations where this becomes the wrong answer:
First, if you are performing a complex operation like parsing a file, and its and all-or-nothing -- if one field in the file is corrupt, you want to bail on the whole operation. Exceptions allow you to jump out of the whole complex process up to an exception handler encapsulating the entire parse. Sure, you could litter the parsing code with checks and return values and checks on the return values -- but its going to be a lot cleaner just to throw the exception and let it rise up to the top of the operation. Even if you expect that the input is going to be bad sometimes, if there isn't a reasonable way to handle the error exactly at the point where the error occurs, use exceptions to let the error rise up to a more appropriate place to handle it. Thats really what exceptions were for in the first place -- getting rid of all that error handling code down in the details, and moving it to one, consolidated, reasonable place.
Second, a library might not let you make the choice. For example, int.TryParse is a good alternative to int.Parse if the input hasn't already been vetted. On the other hand, a library might not have a non-exception-throwing option. In that case, don't brew up your own code to check without exceptions -- though it might be bad form to use exception handling to check for an expected condition, its worse form to duplicate the functionality of the library, just to avoid an exception. Just use the try/catch, and maybe add a snide comment about how you didn't WANT to do it, but the library authors MADE you :).
For your particular example, probably stick with the exception. While exception handling isn't considered 'fast,' its still faster than a round trip to the database; and there isn't going to be a reasonable way to check for that exception without sending the command anyways. Plus, hitting a database in interfacing with an external system -- that in itself is a pretty to good reason to expect the unexpected -- exception handling almost always makes sense when you are leaving your particular controlled environment.
Or, more specifically to your example, you may consider using a stored procedure with a MERGE statement, to use the source data in table to update or insert as appropriate; the update will be a little friendlier on all fronts than doing a delete-then-insert for existing keys.
try catches are expensive on performance, so don't use them as control structures. Instead use triggers at the database level.
One problem is that any exception caused by call of SqlUpload() in the catch block causes the application to crash, because there is no further exception handling.
You'll probably get a few different opinions on this, but mine is that try...catch should be used for things that shouldn't normally happen (although sometimes it's unavoidable). So by that rule, you should ask if the duplicates are in the table by normal execution of the program or if they should not exist given allowable execution of the program.
Just to clarify, I'm saying "normal" usage of the program, not "correct" usage (e.g. when I test it the duplicates don't appear (correct usage) but when the customer uses it they do (perhaps incorrect but normal), so I need to get rid of them). It's more that the duplicates would only appear in a way that the program cannot control (e.g. sometimes someone goes into the database and adds a duplicate row (hopefully not a normal situation)).
Something like duplicate rows, though, is likely a symptom of some other bug, so you shouldn't mask it but try and find the root cause so that the deletion isn't necessary.
When using try-catch in methods, if you want you application to continue even if errors come along, is it okay to return the default value as return through the catch block, and log the error for later review?
For Example:
public static string GetNameById(int id)
{
string name;
try
{
//Connect to Db and get name - some error occured
}
catch(Exception ex)
{
Log(ex);
name = String.Empty;
}
return name;
}
Example 2:
public static string GetIdByName(string name)
{
int id;
try
{
//Connect to Db and get id- some error occured
}
catch(Exception ex)
{
Log(ex);
id = 0;
}
return id;
}
Is it okay to return any default value (depending on the return type of the method ...???) so that the application logic that required the result from this method do not crash and keeps going ....
Thanks in advance...
Regards.
The advice for exception handling is that mostly you should only catch exceptions that you can do something about (e.g. retry an operation, try a different approach, elevate security etc). If you have logging elsewhere in your application at a global level, this kind of catch-log-return is unnecessary.
Personally - typically - in this situation I'd do this:
public static string GetNameById(int id)
{
string name;
try
{
//Connect to Db and get name - some error occured
}
catch(Exception ex)
{
Log(ex);
throw; // Re-throw the exception, don't throw a new one...
}
return name;
}
So as usual - it depends.
Be aware of other pitfalls though, such as the calling method not being aware that there was a failure, and continuing to perform work on the assumption that the method throwing the exception actually worked. At this point you start the conversation about "return codes vs. throwing exceptions", which you'll find a lot of resources for both on SO.com and the internets in general.
I do not think that is a good solution. In my opinion it would be better to let the caller handle the exception. Alternatively you can catch the exception in the method and throw a custom exception (with the caught exception as the inner exception).
Another way of going about it would be to make a TryGet method, such as:
public static bool TryGetNameById(int id, out string name)
{
try
{
//Connect to Db and get name - some error occured
name = actualName
return true;
}
catch(Exception ex)
{
Log(ex);
name = String.Empty;
return false;
}
}
I think this approach is more intention revealing. The method name itself communicates that it may not always be able to produce a useful result. In my opinion this is better than returning some default value that the caller has to be able to know about to do the correct business logic.
My opinion is I'll never mute errors.
If some exception is thrown, it should be treated as a fatal error.
Maybe the problem is throwing exceptions for things that aren't exceptions. For example, business validation shoudn't be throwing such exceptions.
I'd prefer to validate the business and translate the errors in "broken rules" and transmit them to the presentation or wherever, that would save CPU and memory because there's no stack trace.
Another situation is a data connection loss or another situation that makes the application fall in a wrong state. Then, I'd prefer to log the error and prompt the user to re-open the application or maybe the application may restart itself.
I want to make you some suggestion: have you ever heard about PostSharp? Check it, you can implement that exception logging with an AOP paradigm.
It is advised that you only catch errors that you can handle and recover from. Catching and consuming exceptions that you cannot handle is bad form. However, some environments / applications define strict rules that go against this ideal behaviour.
In those cases, I would say in cases you don't have a choice, you can do what you like with returns - it is up to your application to work with them.
Based on the assumption that your application can handle any sort of failure in trying to get an ID, then returning a default ID is a good enough choice. You can go further and use something like the special case pattern to return empty / missing objects, but for simple data types this seems unwarranted.
this depends very much on the context and on the way your calling method is designed. I have used to return default values in the past as you are doing now and I understood only afterwards that it was deeply wrong...
you should imagine the catch block to throw the exception back, after logging it properly, then the calling method could have another try catch and depending on the severity of the error could inform the user or behave accordingly.
the fact is that if you return an empty string, in some cases, could be that the caller "thinks" there is a user with empty name, while would probably be better to notify the user that the record was not found, for example.
depending on the way your logger works you could log the exception only where you handle it and not in all catches...
That depends on what you want. If it's important for you that you log the exception, but that everything else keeps working, then this is - in my honest opinion- ok.
On the other hand: if an exception occurs, you have to make sure this does not have an impact on the further working of your application.
The point of a try/catch is to allow you to catch and handle errors in a graceful manor, allowing application execution to continue, rather than simply crashing the application and stopping execution.
Therefore it is perfectly acceptable to return a default value. However, be sure that all following code will continue to function if a default value is returned rather than causing further errors.
Eg - in your example, if the DB connection fails, ensure there are no further commands to edit / retrieve values from the database.
It REALLY depends. In most scenarios it is not - problems i that if there is a scenario specific issue you amy never find out. Soemtiems a recovery attempt is good. This normalyl depends on circumstances and actual logic.
The scenarios where "swallow and document" are really valid are rare and far in between in the normal world. They come in more often when writing driver type of thigns (like loaded moduels talkign to an external system). Whether a return value or default(T) equivalent maeks sense also depends.
I would say in 99% of the cases let the exception run up. In 1% of the cases it may well make sense to return some sensible default.
It is better to log the exception but then re-trow it so that it can be properly handled in the upper layers.
Note: the "log the exception part" is of course optional and depends a lot on your handling strategy(will you log it again somewhere else?)
Instead of making the app not crash by swalowing exception, it is better to let them pass and try to find the root cause why they were thrown in the first place.
Depends on what you want your app to do...
For example, display a friendly message, "Cannot Login" if you get a SqlException when trying to connect to the Database is OK.
Handling all errors is sometimes considered bad, although people will disagree...
Your application encountered an exception you did not expect, you can no longer be 100% sure what state your application is in, which lines of codes executed and which didn't, etc. Further reading on this: http://blogs.msdn.com/b/larryosterman/archive/2005/05/31/423507.aspx.
And more here : http://blogs.msdn.com/b/oldnewthing/archive/2011/01/20/10117963.aspx
I think the answer would have to be "it depends".
In some cases it may be acceptable to return an empty string from a function in case of an error. If you are looking up somebody's address to display then an empty string works fine rather than crashing the whole thing.
In other cases it may not work so well. If you are returning a string to use for a security lookup for example (eg getSecurityGroup) then you are going to have very undesired behaviour if you return the wrong thing and you might be better off keeping the error thrown and letting the user know something has gone wrong rather than pretending otherwise.
Even worse might be if you are persisting data provided to you by the user. Something goes wrong when you are getting their data, you return a default and store that without even telling them... That's gotta be bad.
So I think you need to look at each method where you are considering this and decide if it makes sense to throw an error or return a default value.
In fact as a more general rule any time you catch an error you should be thinking hard about whether it is an acceptable error and continuing is permissable or whether it is a show stopping error and you should just give up.
I have a Result object that lets me pass around a List of event messages and I can check whether an action was successful or not.
I've realized I've written this code in alot of places
Result result;
try
{
//Do Something
...
//New result is automatically a success for not having any errors in it
result = new Result();
}
catch (Exception exception)
{
//Extension method that returns a Result from the exception
result = exception.ToResult();
}
if(result.Success) ....
What I'm considering is replacing this usage with
public static Result CatchException(Action action)
{
try
{
action();
return new Result();
}
catch (Exception exception)
{
return exception.ToResult();
}
}
And then use it like
var result = Result.CatchException(() => _model.Save(something));
Does anyone feel there's anything wrong with this or that I'm trading reusability for obscurity?
Edit: The reason I am trapping all exceptions is I use this code inside of my ViewPresenter classes at any point I interact with my model since if I get an unhandled exception I'd rather display the actual error to the user (internal app) as opposed to just redirecting them the generic error page.
I don't think there is anything wrong with using a functional approach, and passing in a lambda. That is perfectly valid.
That being said, I'd question your use in this specific scenario. Trapping all exceptions into a general purpose "Result" class seems dangerous. Ideally, you should be catching exceptions which you can handle correctly - not every possible exception and continuing.
That being said, if you really want to do this, I have a couple of suggestions for you:
1) I'd make a static, immutable result for success, and just do:
result = result.Success;
This avoids generating a new "success" each time you succeed, which hopefully is the most common option.
2) I'd probably avoid the extension method, and do:
result = new Result(exception);
This will be much more clear and obvious in intent, and there's really no reason to do an extension method in this case...
You shouldn't be catching Exception like this. You should only be catching known exception types that you know how to handle.
If you did that, you code would no longer be so repetitive, so there would be no case for using this pattern for re-usability.
All round this looks like a very bad idea, not just the lambda pattern, I'm talking about the handling of exceptions by converting them into results objects. You are basically allowing yourself to ignore all exceptions and continue working. There is a reason why C# error handling is done with exceptions and not with return codes, and that is because exceptions allow for structured, hierarchical and call stack based handling. Unless you have simplified the code for this question, I would reconsider your exception handling process.
In general though, I don't see anything wrong with the lambda pattern. I use something similar myself for wrapping multiple retries of a code block. But in this case I don't think it's what you need.
If you feel the need to write such an automated exception handler system you may be over-using exceptions, which could have serious performance implications.
However, this appears to be a generic system for converting exceptions into error codes - so why not just use error codes in the first place? Or learn to use exceptions more effectively so you don't feel the need to convert them into error codes? The fact that you are trying to convert them to something else should raise alarms and suggest to you that you're missing the point somewhere.