I am downloading data from text files into db tables. The data in the files is occasionally corrupt at a field level (files are comma delimited .csv files)
I am reading each line into an object that represents the data line with properties that are the correct datatype.
If the read into the object fails due to dodgy data, I want to read the line into a similar object as the first one, only this one has all data types set to string so the read into it should not fal.
The idea being that I can create a collection of valid record objects which I will load in to the appropriate db table, and a collection of exceptions which I will load into an exceptions table. These can then be dealt with later.
So - the question:
I am going to loop through the lines of the text file and load these into the object and add the object to a collection. There will be a try/catch loop around this and if the object load fails, then in the catch section I will load the exception object and add this to the collection of exceptions.
However, what happens if the exception object load fails (for whatever reason). Do I put a try/catch around that and log exceptions - i.e a try/catch within a try/catch?
Is there a better way of doing this?
Code within a catch block is no way different to other code.
So you will have to protect every critical action with a try catch otherwise your program might crash.
2.
This might be a personal flavor, but I do not recommend to use try for control flow - do use if instead. So use if-statements to detect your dodgy data.
Yes. You can add the Try-Catch in other catch clause. It's OK.
Or as Imapler suggested, you can add the exception to a collection, and then process the collection in a loop. That's will let you process the lines with the exception later. But maybe it looks better than Try-Catch in a Catch clause.
var exceptionList = new List<ExceptionLines>();
try
{
// read lines, parse...
}
catch(Exception ex)
{
// handle the lines with the exception. Add the exception and the necessary arguments to the collection
exceptionList.Add( new ExceptionLines(....));
}
// do stuff
// handle the exceptions.
foreach(var exception in exceptionList)
{
try
{
// process the exception line.
}
catch(Exception ex)
{
// log error and handle exception
}
}
You can also wrap the exception with a wrapper. Maybe it will looks better.
// somewhere in your code...
WrapException( () =>
{
// read and parse lines...
}, (ex) =>
{
WrapException(ex, ParseToExceptionFunction, HandleExceptionParseFunction, false);
}, false);
void WrapException(Action func, Action<Exception> handleCatch, bool rethrow)
{
try
{
func();
}
catch(Exception ex)
{
handleCatch(ex);
if (rethrow)
throw;
}
}
static void WrapException<T>(T arg, Action<T> func, Action<Exception> handleCatch, bool rethrow)
{
try
{
func(arg);
}
catch (Exception ex)
{
handleCatch(ex);
if (rethrow)
throw;
}
}
void ParseToExceptionFunction(ArgType arg)
{
// try to parse to excetion
}
void HandleExceptionParseFunction(Exception ex)
{
// handle the exception for parsing the line with the exception
}
You can also implement the ParseToExceptionFunction and the HandleExceptionParseFunction as lambdas...
So I used everybody's advice.
Used if than else's to catch dodgy data, created a list of good data and a list of exceptions (raised by the if and else's) and then processed the lists in try / catches to catch any other exceptions that may arile (ref integrity issues etc)
Thanks for the advice.
Related
This might be a broad question, but recently I ahve wondered about the following: In our C# backend we have many places that wrap some code in a try/catch block, specifically calls to external WcF services. Some of these calls are crucial for the application so in the catch block we log the error and rethrow, like:
catch(Exception ex)
{
_logger.Error("Some good error message");
throw ex;
}
On the other hand there are services we allow to fail, but we still want to log the error, so they look like:
catch(Exception ex)
{
_logger.Error("Some good error message");
}
Now reading the code of team members I can not be sure if they forgot to throw or if this is the intended behaviour.
Q: Is there a way, resp. what is the default way, to explicitly NOT rethrow (without including a comment in the code).
I have considered something like this:
catch(Exception ex)
{
_logger.Error("Some good error message");
NotThrowingHereOnPurpose();
}
// ...
// and further below a private method
// ...
private void NotThrowingHereOnPurpose(){}
One approach that may be useful here is to change the way of invoking the code that you explicitly allow to fail in such a way that it does not look like a try/catch block at all.
For example, you could write a helper method that does error reporting, and call it with actions expressed as lambdas:
void InvokeFailSafe(Action action, Action<Exception> onFailure = null) {
try {
action();
} catch (Exception e) {
if (onFailure != null) {
onFailure(e);
}
}
}
Now instead of try/catch you would write this:
InvokeFailSafe(
() => {
... The code that may fail
}
, exception => _logger.Error("Some good error message: {0}", exception)
);
or like this, if you don't want anything logged:
InvokeFailSafe(
() => {
... The code that may fail
}
);
If you code things this way, there would be no doubts about a missing throw statement.
It's an opposite solution to dasblinkenlight's answer. Instead of notifying others that the exception mustn't be rethrown it would say that it must be.
If you only want to log it then use the Error method as usual. Otherwise, you can write an extension method for your logger to log and throw exceptions.
The method would take the catched exception and rethrow it using the ExceptionDispatchInfo class. The ExceptionDispatchInfo is used to rethrow the exception with the original stack trace information and Watson information. It behaves like throw; (without the specified exception).
public static void ErrorAndThrow(this ILogger logger, string message, Exception exception)
{
var exceptionInfo = ExceptionDispatchInfo.Capture(exception);
logger.Error(message);
exceptionInfo.Throw();
}
And use it this way:
try
{
}
catch (Exception ex)
{
// ex would be rethrown here
_logger.ErrorAndThrow("Some good error message", ex);
}
Q: Is there a way, resp. what is the default way, to explicitly NOT
rethrow (without including a comment in the code).
Ideal way would be not to catch a generic exception. Now, to throw or not that entirely depends on your case. You need to understand that Exception handling is used when you know what to do in case an exception occurs. So, only specific exceptions should be handled. Catching exceptions without knowing what you are catching will change the behavior of your application.
Now reading the code of team members I can not be sure if they forgot
to throw or if this is the intended behaviour.
This is something the author of the code can explain to you. But here is a learning to take from this. Your code should be self explanatory. In specific cases where you are unable to express yourself with the code, add a meaningful comment.
You can check this link for better understanding.
I actually found another way that kind of includes what other have suggested here, but uses a built in feature: exception filters. I was free to modify the example given in here to illustrate this:
public void MethodThatFailsSometimes()
{
try {
PerformFailingOperation();
}
catch (Exception e) when (e.LogAndBeCaught())
{
}
}
and then one could have two extension methods on Exception, say LogAndBeCaught and LogAndEscape like so:
public static bool LogAndBeCaught(this Exception e)
{
_logger.Error(#"Following exception was thrown: {e}");
return true;
}
public static bool LogAndEscape(this Exception e)
{
_logger.Error(#"Following exception was thrown: {e}");
return false;
}
I am reading a file line by line from text file and do some processing. The problem is that if some error occurs at some line. Then an exception is generated, what I want is that I want to ignore that error and move to the next line to read.
But if an exception is generated then I cant continue reading input lines. Please help.
If I'm assuming what you're asking for correctly, here's a basic outline of what your code could look like:
using (StreamReader reader = File.OpenText("Path\to\your\file"))
{
string line = null;
while ((line = reader.ReadLine()) != null)
{
try
{
ProcessLine(line);
}
catch { /* Ignore exceptions */ }
}
}
It's generally not a good idea to blindly catch all exceptions, so if you can, you should filter the exceptions caught by your catch block to something more specific.
See exception handling. http://msdn.microsoft.com/en-us/library/0yd65esw(v=vs.71).aspx
If you really want to "ignore" exceptions, you can do something like:
try
{
foo(); // Something that may throw an exception
}
catch
{
}
See http://msdn.microsoft.com/en-us/library/0yd65esw(v=vs.80).aspx for more info.
But usually, an exception means something bad happened, and you'll probably want to handle that somehow.
try
{
//put the statement throwing the exception here
}
catch
{
//will eat the exception
}
//execution will continue here
Difficult to understand what you want to achieve, but you probably are asking for something like this:
while(condition)
{
try {
//process file line here
}
catch (Exception ex) {
LogException(ex);
}
}
Not a good design decision in my opinion, by the way. Avoid it if you can.
Use a try catch and log the error. Your code would look like this:
try
{
//read lines here
}
catch(Exception ex)
{
//log the exception but don't throw anything.
}
You may be tempted to do nothing in the catch, but you will likely regret it later.
Try catch article:
http://www.homeandlearn.co.uk/csharp/csharp_s5p6.html
You simply need to wrap your processing code in a try / catch block.
try
{
DoSomeProcessing(lineThatIreadFromFile);
}
catch
{
// Log or Ignore error here
}
However, please note that typically, just swallowing exceptions is never a good idea. You should either fail your program (if unrecoverable), or potentially log those somewhere so you can fix why your program is failing.
Based on the very limited information you provide there are two things you can do:
Enclose the offending line with an empty catch block. Wait for next maintainer to do bad things to you.
Understand why the exception is happening and modify the code such that the next maintainer understands why it is safe that you ignored a certain condition
This is not a good approach. You should be proactive and catch specific exceptions you can recover from. Catch them as close to the place where they are thrown from. And let the rest of them bubble up and terminate the process. By swallowing all exceptions you will get an illusion of robustness while in fact your code may be full of bugs. There is simply no 'quick and dirty' approach to exception handling. See this answer.
Avoid handling errors by catching non-specific exceptions, such as
System.Exception, System.SystemException, and so on, in application
code. There are cases when handling errors in applications is
acceptable, but such cases are rare.
An application should not handle exceptions that can result in an
unexpected or exploitable state. If you cannot predict all possible
causes of an exception and ensure that malicious code cannot exploit
the resulting application state, you should allow the application to
terminate instead of handling the exception.
You need:
using System.IO;
to get this to work.
You can try:
try
{
string path = ""; // You must add the path here. Else it won't work.
string[] lines = File.ReadAllLines(path);
foreach(string line in lines)
{
Console.WriteLine(line);
}
} catch (Exception ex, IOException ioex) {
// It's optional. You can remove "Exception ex, IOException ioex" if you want. You can delete the code below too.
Console.WriteLine(ex.ToString());
Console.WriteLine();
Console.WriteLine(ioex.ToString());
} finally
{
// in this "finally" section, you can place anything else. "finally" section isn't important, just shows that method has no exceptions.
// you can add something else like: Console.WriteLine("Code has no exceptions. Great!");
}
Good for advanced notepads.
EDIT: If you don't like the previous solution, this one can help you.
string path = ""; // Again, path.
string[] lines = File.ReadAllLines(path);
foreach(string line in lines)
{
try
{
Console.WriteLine(line);
} catch(Exception ex, IOException ioex)
{ /* exception */ }
}
----- or -----
string path = Console.ReadLine();
int turns = 0;
int maxturns = (File.ReadAllLines(path)).Count();
while (turns < maxturns)
{
try
{
Console.WriteLine(File.ReadLines(path).Skip(turns).Take(1).First());
} catch (Exception ex, IOException ioex) { /* exception */ }
turns++;
}
I am confused about the order of try, catch and finally block execution.
I also want to know when should I use try-catch block and what should I put in the try-catch block?
I also want to know if some exception comes in try block then if an action is taken corresponding to try block then which one is executed first catch or finally (which is always to be executed)?
After the execution of these two does control return to try block or it leave it?
If you have (note: this is not valid C#, see below for a valid example):
try {
// ... some code: A
} catch(...) {
// ... exception code: B
} finally {
// finally code: C
}
Code A is going to be executed. If all goes well (i.e. no exceptions get thrown while A is executing), it is going to go to finally, so code C is going to be executed. If an exception is thrown while A is executed, then it will go to B and then finally to C.
As an example, here's a valid C# code block from http://msdn.microsoft.com/en-us/library/dszsf989.aspx:
public class EHClass
{
void ReadFile(int index)
{
// To run this code, substitute a valid path from your local machine
string path = #"c:\users\public\test.txt";
System.IO.StreamReader file = new System.IO.StreamReader(path);
char[] buffer = new char[10];
try
{
file.ReadBlock(buffer, index, buffer.Length);
}
catch (System.IO.IOException e)
{
Console.WriteLine("Error reading from {0}. Message = {1}", path, e.Message);
}
finally
{
if (file != null)
{
file.Close();
}
}
// Do something with buffer...
}
}
The reason to use try/catch/finally is to prevent your program to fail if there is an error in some code (A in the above example). If there is a problem, you can use catch part to catch the problem and do something useful, such as inform the user, log the exception to a log file, try again or try something different that you suppose might work instead of what you tried originally.
finally is used to ensure that some cleanup is performed. E.g. in A you might try to open a file and read it. If opening succeeds, but read fails, you will have an open file dangling. What you would like in that case is to have it closed, which you would do in finally block - this block always gets executed, guaranteeing the closing of the file.
Take a look here for more info:
http://msdn.microsoft.com/en-us/library/0yd65esw.aspx
http://www.c-sharpcorner.com/UploadFile/puranindia/75/Default.aspx
A try ... catch block is used to catch exceptions. In the try block you put the code that you expect may raise an exception.
If no exception occurs then the code in the try block completes as expected. If there's a finally block then that will execute next.
If an exception does occur then execution jumps to the start of the first matching catch block. Once that code is complete the finally block (if it exists) is executed. Execution does not return to the try block.
You should almost never use try/catch.
You should only catch exceptions that you can actually correct, and only when you're expecting them. Otherwise, let the caller handle the exception - or not.
If used, any catch clauses are executed first - only one of them.
Then, finally is "finally" executed.
This has been stated better in many places, but I'll try. The following code:
try
{
// Do something here
}
catch (Exception ex)
{
MessageBox.Show("Friendly error message");
}
does not fix the exception. It hides the exception so that the problem will never be fixed. That code has no idea which exception was thrown, because it will catch all of them, and it does nothing to correct the problem - it just tells the user a polite fiction.
The fact of the matter is that the code above should be replaced with the following:
// Do something here
This way, if the caller of this method knows how to fix particular problems, then the caller can fix them. You will not have removed that option from the caller.
If the caller does not know how to fix the problem, then the caller should also not catch the exception.
Here is an example (from MSDN) of using exceptions in a reasonable manner. It's a modified form of the example in the documentation of the SmtpFailedRecipientsException Class.
public static void RetryIfBusy(string server)
{
MailAddress from = new MailAddress("ben#contoso.com");
MailAddress to = new MailAddress("jane#contoso.com");
using (
MailMessage message = new MailMessage(from, to)
{
Subject = "Using the SmtpClient class.",
Body =
#"Using this feature, you can send an e-mail message from an application very easily."
})
{
message.CC.Add(new MailAddress("Notifications#contoso.com"));
using (SmtpClient client = new SmtpClient(server) {Credentials = CredentialCache.DefaultNetworkCredentials})
{
Console.WriteLine("Sending an e-mail message to {0} using the SMTP host {1}.", to.Address, client.Host);
try
{
client.Send(message);
}
catch (SmtpFailedRecipientsException ex)
{
foreach (var t in ex.InnerExceptions)
{
var status = t.StatusCode;
if (status == SmtpStatusCode.MailboxBusy || status == SmtpStatusCode.MailboxUnavailable)
{
Console.WriteLine("Delivery failed - retrying in 5 seconds.");
System.Threading.Thread.Sleep(5000); // Use better retry logic than this!
client.Send(message);
}
else
{
Console.WriteLine("Failed to deliver message to {0}", t.FailedRecipient);
// Do something better to log the exception
}
}
}
catch (SmtpException ex)
{
// Here, if you know what to do about particular SMTP status codes,
// you can look in ex.StatusCode to decide how to handle this exception
// Otherwise, in here, you at least know there was an email problem
}
// Note that no other, less specific exceptions are caught here, since we don't know
// what do do about them
}
}
}
Note that this code uses try/catch to surround a small piece of code. Within that try/catch block, if an SmtpException or SmtpFailedRecipientsException is thrown, we know what to do about it. If, for instance, we were to catch IOException, we would not know what it meant, or what to do about it. Any exception you don't actually know how to correct should not be caught, except maybe to add information to the exception, log it, and rethrow.
Here is an example:
try
{
someFunctionThatWorks();
functionThatThrowsAnException(); // As soon as this function throws an exception we are taken to the catch block
anotherFunction(); // <-- This line will never get executed
}
catch(Exception e)
{
// Here you can handle the exception, if you don't know how to handle it you should not be catching it
// After this you will not be taken back to the try block, you will go right to the finally block
}
finally
{
// Code here is always executed at the very end, regardless of whether an exception was thrown or not
}
I'd like to elaborate a bit on this and extend #icyrock.com answer with scenario when you rethrow the exception in the catch block so it is handled lower on the execution stack...
I gave it a try with the following code:
static void Main(string[] args)
{
try
{
// pick one:
// NormalExcecution();
// TroubleExcecution();
}
catch
{
Console.WriteLine("block D");
}
Console.ReadKey();
}
private static void NormalExcecution()
{
try
{
Console.WriteLine("block A");
}
catch (Exception)
{
Console.WriteLine("block B");
throw;
}
finally
{
Console.WriteLine("block C");
}
}
private static void TroubleExcecution()
{
try
{
Console.WriteLine("block A");
throw new Exception();
}
catch (Exception)
{
Console.WriteLine("block B");
throw;
}
finally
{
Console.WriteLine("block C");
}
}
So when there is no exception in block A, then the sequence is as follows (exception handling blocks are never hit):
Block A
Block C
When there's some problem with block A, the sequence is as follows:
block A
block B
block C
block D
Another words, the occurring exception is first handled by block B, then the finally clause is executed, only after that the exception is rethrown and handled lower on the execution stack (block D).
Please mind I may be wrong with what is actually going on under the hood of the .NET framework - I just present the results I observed :)
Situation:
My application need to process the first step in the business rules (the initial try-catch statement). If an certain error occurs when the process calls the helper method during the step, I need to switch to a second process in the catch statement. The back up process uses the same helper method. If an same error occurs during the second process, I need to stop the entire process and throw the exception.
Implementation:
I was going to insert another try-catch statement into the catch statement of the first try-catch statement.
//run initial process
try
{
//initial information used in helper method
string s1 = "value 1";
//call helper method
HelperMethod(s1);
}
catch(Exception e1)
{
//backup information if first process generates an exception in the helper method
string s2 = "value 2";
//try catch statement for second process.
try
{
HelperMethod(s2);
}
catch(Exception e2)
{
throw e2;
}
}
What would be the correct design pattern to avoid code smells in this implementation?
I caused some confusion and left out that when the first process fails and switches to the second process, it will send different information to the helper method. I have updated the scenario to reflect the entire process.
If the HelperMethod needs a second try, there is nothing directly wrong with this, but your code in the catch tries to do way too much, and it destroys the stacktrace from e2.
You only need:
try
{
//call helper method
HelperMethod();
}
catch(Exception e1)
{
// maybe log e1, it is getting lost here
HelperMethod();
}
I wouldn't say it is bad, although I'd almost certainly refactor the second block of code into a second method, so keep it comprehensible. And probably catch something more specific than Exception. A second try is sometimes necessary, especially for things like Dispose() implementations that might themselves throw (WCF, I'm looking at you).
The general idea putting a try-catch inside the catch of a parent try-catch doesn't seem like a code-smell to me. I can think of other legitimate reasons for doing this - for instance, when cleaning up an operation that failed where you do not want to ever throw another error (such as if the clean-up operation also fails). Your implementation, however, raises two questions for me: 1) Wim's comment, and 2) do you really want to entirely disregard why the operation originally failed (the e1 Exception)? Whether the second process succeeds or fails, your code does nothing with the original exception.
Generally speaking, this isn't a problem, and it isn't a code smell that I know of.
With that said, you may want to look at handling the error within your first helper method instead of just throwing it (and, thus, handling the call to the second helper method in there). That's only if it makes sense, but it is a possible change.
Yes, a more general pattern is have the basic method include an overload that accepts an int attempt parameter, and then conditionally call itself recursively.
private void MyMethod (parameterList)
{ MyMethod(ParameterList, 0)l }
private void MyMethod(ParameterList, int attempt)
{
try { HelperMethod(); }
catch(SomeSpecificException)
{
if (attempt < MAXATTEMPTS)
MyMethod(ParameterList, ++attempt);
else throw;
}
}
It shouldn't be that bad. Just document clearly why you're doing it, and most DEFINITELY try catching a more specific Exception type.
If you need some retry mechanism, which it looks like, you may want to explore different techniques, looping with delays etc.
It would be a little clearer if you called a different function in the catch so that a reader doesn't think you're just retrying the same function, as is, over again. If there's state happening that's not being shown in your example, you should document it carefully, at a minimum.
You also shouldn't throw e2; like that: you should simply throw; if you're going to work with the exception you caught at all. If not, you shouldn't try/catch.
Where you do not reference e1, you should simply catch (Exception) or better still catch (YourSpecificException)
If you're doing this to try and recover from some sort of transient error, then you need to be careful about how you implement this.
For example, in an environment where you're using SQL Server Mirroring, it's possible that the server you're connected to may stop being the master mid-connection.
In that scenario, it may be valid for your application to try and reconnect, and re-execute any statements on the new master - rather than sending an error back to the caller immediately.
You need to be careful to ensure that the methods you're calling don't have their own automatic retry mechanism, and that your callers are aware there is an automatic retry built into your method. Failing to ensure this can result in scenarios where you cause a flood of retry attempts, overloading shared resources (such as Database servers).
You should also ensure you're catching exceptions specific to the transient error you're trying to retry. So, in the example I gave, SqlException, and then examining to see if the error was that the SQL connection failed because the host was no longer the master.
If you need to retry more than once, consider placing an 'automatic backoff' retry delay - the first failure is retried immediately, the second after a delay of (say) 1 second, then doubled up to a maximum of (say) 90 seconds. This should help prevent overloading resources.
I would also suggest restructuring your method so that you don't have an inner-try/catch.
For example:
bool helper_success = false;
bool automatic_retry = false;
//run initial process
try
{
//call helper method
HelperMethod();
helper_success = true;
}
catch(Exception e)
{
// check if e is a transient exception. If so, set automatic_retry = true
}
if (automatic_retry)
{ //try catch statement for second process.
try
{
HelperMethod();
}
catch(Exception e)
{
throw;
}
}
Here's another pattern:
// set up state for first attempt
if(!HelperMethod(false)) {
// set up state for second attempt
HelperMethod(true);
// no need to try catch since you're just throwing anyway
}
Here, HelperMethod is
bool HelperMethod(bool throwOnFailure)
and the return value indicates whether or not success occurred (i.e., false indicates failure and true indicates success). You could also do:
// could wrap in try/catch
HelperMethod(2, stateChanger);
where HelperMethod is
void HelperMethod(int numberOfTries, StateChanger[] stateChanger)
where numberOfTries indicates the number of times to try before throwing an exception and StateChanger[] is an array of delegates that will change the state for you between calls (i.e., stateChanger[0] is called before the first attempt, stateChanger[1] is called before the second attempt, etc.)
This last option indicates that you might have a smelly setup though. It looks like the class that is encapsulating this process is responsible for both keeping track of state (which employee to look up) as well as looking up the employee (HelperMethod). By SRP, these should be separate.
Of course, you need to a catch a more specific exception than you currently are (don't catch the base class Exception!) and you should just throw instead of throw e if you need to rethrow the exception after logging, cleanup, etc.
You could emulate C#'s TryParse method signatures:
class Program
{
static void Main(string[] args)
{
Exception ex;
Console.WriteLine("trying 'ex'");
if (TryHelper("ex", out ex))
{
Console.WriteLine("'ex' worked");
}
else
{
Console.WriteLine("'ex' failed: " + ex.Message);
Console.WriteLine("trying 'test'");
if (TryHelper("test", out ex))
{
Console.WriteLine("'test' worked");
}
else
{
Console.WriteLine("'test' failed: " + ex.Message);
throw ex;
}
}
}
private static bool TryHelper(string s, out Exception result)
{
try
{
HelperMethod(s);
result = null;
return true;
}
catch (Exception ex)
{
// log here to preserve stack trace
result = ex;
return false;
}
}
private static void HelperMethod(string s)
{
if (s.Equals("ex"))
{
throw new Exception("s can be anything except 'ex'");
}
}
}
Another way is to flatten the try/catch blocks, useful if you're using some exception-happy API:
public void Foo()
{
try
{
HelperMethod("value 1");
return; // finished
}
catch (Exception e)
{
// possibly log exception
}
try
{
HelperMethod("value 2");
return; // finished
}
catch (Exception e)
{
// possibly log exception
}
// ... more here if needed
}
An option for retry (that most people will probably flame) would be to use a goto. C# doesn't have filtered exceptions but this could be used in a similar manner.
const int MAX_RETRY = 3;
public static void DoWork()
{
//Do Something
}
public static void DoWorkWithRetry()
{
var #try = 0;
retry:
try
{
DoWork();
}
catch (Exception)
{
#try++;
if (#try < MAX_RETRY)
goto retry;
throw;
}
}
In this case you know this "exception" probably will happen so I would prefer a simple approach an leave exceptions for the unknown events.
//run initial process
try
{
//initial information used in helper method
string s1 = "value 1";
//call helper method
if(!HelperMethod(s1))
{
//backup information if first process generates an exception in the helper method
string s2 = "value 2";
if(!HelperMethod(s2))
{
return ErrorOfSomeKind;
}
}
return Ok;
}
catch(ApplicationException ex)
{
throw;
}
I know that I've done the above nested try catch recently to handle decoding data where two third party libraries throw exceptions on failure to decode (Try json decode, then try base64 decode), but my preference is to have functions return a value which can be checked.
I generally only use the throwing of exceptions to exit early and notify something up the chain about the error if it's fatal to the process.
If a function is unable to provide a meaningful response, that is not typically a fatal problem (Unlike bad input data).
It seems like the main risk in nested try catch is that you also end up catching all the other (maybe important) exceptions that might occur.
Simple best practice question.
Should you nest try catch statements or just use methods.
For instance, if you have a method that opens a file does work and closes the file, you would have the open and close outside the try catch, or rather the close in the finally block.
Now if your open method fails, the method would assert right? So should your wrap that in a try catch block or should that be called from another method, which in turn as a try catch block?
In the context of a method that opens a file I would use a using statement vs a try catch. The using statement ensures that Dispose is called if an exception occurs.
using (FileStream fs = new FileStream(file, FileMode.Open))
{
//do stuff
}
does the same thing as:
FileStream fs;
try
{
fs = new FileStream(file, FileMode.Open);
//do Stuff
}
finally
{
if(fs!=null)
fs.Dispose();
}
Now that we have lambdas and type inference and some other stuff, there's an idiom that is common in other languages which now makes a lot of sense in C#. Your example was about opening a file, doing something to it, and then closing it. Well, now, you can make a helper method which opens a file, and also takes care of making sure to close / dispose / clean up, but calls out to a lambda you provide for the "do stuff" portion. This will help you get the complicated try/catch/finally dispose/cleanup stuff right in one place, and then use it over and over.
Here's an example:
public static void ProcessFile(string filePath, Action<File> fileProcessor)
{
File openFile = null;
try
{
openFile = File.Open(filePath); // I'm making this up ... point is you are acquiring a resource that needs to be cleaned up after.
fileProcessor(openFile);
}
finally
{
openFile.Close(); // Or dispose, or whatever.
}
}
Now, callers of this method don't have to worry about how to open the file or close / dispose of it. They can do something like this:
Helpers.ProcessFile("C://somefile.txt", f =>
{
while(var text = f.ReadLine())
{
Console.WriteLine(text);
}
});
This is a style question but for me I try to never have more than one level of try/catch/finally nesting in a single method. At the point you hit a nested try, you've almost certainly violated the 1 function = 1 operation principal and should use a second method.
Depends on what you are trying to do, but in most cases, nested try/catches are a sign of an over-complex function (or of a programmer who doesn't quite know how exceptions work!).
In the case of the open file, I'd use an IDisposable holder and a using clause, and so forgo the need of any explicit try/catch.
How about where you have related code that doesn't necessarily belong in a separate function of it's own right? Would this then be correct?
try
{
// Part 1 Code Here
try
{
// Part 2 Code Here
}
catch (Exception ex)
{
// Error from Part 2
}
}
catch (Exception ex)
{
// Error from Part 1
}
Most of the time I would break up the nested try/catch blocks into functions. But I have sometimes written code to catch and log all uncaught exceptions thrown by my application. But what if the logging code fails? So I have yet another try/catch around that just to prevent the user from seeing the default .NET unhandled exception dialog box. But even this code could very easily be refactored into functions instead of nested try/catch blocks.
try
{
try
{
DoEverything();
}
catch (Exception ex)
{
// Log the exception here
}
}
catch (Exception ex)
{
// Wow, even the log is broken ...
}
//create a switch here and set it to 0
try
{
DoChunk1();
//looks good. set the switch to 1
}
catch (Exception ex)
{
// Log the exception here
}
// check the switch, if it is still zero at this point then you may halt your program here; else set the switch back to zero and execute your next try catch statement. totally agree with breaking them down as mentioned above
try
{
DoChunk2();
//looks good. set the switch to 1
}
catch (Exception ex)
{
// Log the exception here
}
try
{
----
}
catch
{
try
{
---
}
catch
{
---
}
}