Related
Usually, when I work with files and directories and I want to check that a path of a a directory or a file exists, I just use something like that:
if (Directory.Exists(path))
{
//Something...
}
However, if I understood this answer correctly, it is recommended to allow the exception still be thrown, meaning that rather than using if, use try.. catch.
Is that a general approach when working with files and directories or there are times that it is preferable using if(Directory.Exists... or something of that sort?
NOTE: After seeing the first responses, just wanted to clarify that the cases when certain directory/path might not exist is an expected and normal behavior.
You nearly always have to catch exceptions, especially for I/O errors, somewhere, lest the program simply be killed when one occurs.
In many scenarios, it makes sense to also first check for valid input (e.g. Directory.Exists()). This allows you to efficiently and in a user-friendly way report and respond to obvious user-error scenarios.
But you have no guarantee that the directory won't be deleted between the time you execute that call and the time you try to access it in some way. Or that if the directory is on a remote share, the network won't fail. Or that you won't have some other kind of I/O error.
There are a few exceptions that just aren't worth catching. Unexpected OutOfMemoryException for example (as opposed to some data structure simply getting too large), or other types of internal .NET failures. The likelihood of recovering from those types of errors is minimal. But for anything else, you at some point should be catching exceptions that could happen. Sometimes this simply means a top-level catch (Exception e), where you will log the exception in some way before exiting the program cleanly.
(I will note that exceptions that are uncaught and which cause the application to be terminated will generally get logged in the system event log. So as long as users are comfortable inspecting the log and retrieving exception information from there, then there's no need to catch all exceptions…just those you know what to do with).
100% depends on what you want to achieve.
If a path is invalid and you want to inform it to the user, you can choose between returning a success value or throwing an exception by what's more suitable for your code architecture.
In other cases, where something can go wrong without the user being responsible for it, or needing to be informed, you usually let exceptions get thrown and handle them in catch blocks in the appropriate places.
The thing to remember is that you can always perform an if check and throw an exception of your own in case of invalid state, rather than letting the invalid state cause an exception by itself. The main difference there is in the data thrown with the exception (stack trace, message, etc), but can also be expressed in performance (you wouldn't want to try a high-cost operation if you can first perform a low-cost check to make sure it will succeed). Try-catch blocks add a BIT of an overhead as well, but I wouldn't consider that to be significant.
The questions to ask are:
Does invalid state causes the whole operation from above to fail?
Where and how does the code handle invalid state?
Does the code "fix" the invalid state and tries again?
Is the invalid state originating from a user error or a code issue?
How costly the operation is, in contrast to how costly the validation check is?
Edit: Check out Yuval's link in the comment to get better understanding of the costs of try-catch blocks.
The validation check is almost always very low-cost, so in conclusion I would say: Perform the check, even if you intend to throw your own exception in case of invalid state.
So I have been doing some research into how I should be doing try-catch-finally blocks and there is some conflicting information in every post I read. Can someone clarify?
One common idea is to not catch exceptions that you do not know what to do with at that point in the code. The exception will bubble up until it presumably gets to a global exception handler if nothing else catches it. So at that point you display a message to the user that an unknown type of exception occurred, log it, etc.
Now after reading it sounds like this is the only exception handler that you will need? You should not be using it for flow control, so you should be checking if something is returned as null or is invalid causing the exception and correcting it in code. ie. testing for null and doing something about it before it can cause the exception.
But then there are other things such as running out of memory that you would not be able to test for, it would just occur during an operation and the exception would be thrown. But I would not be able to do anything about this either so this would be bubbled up to the global handler.
I think there are some that I am missing, like when dealing with files there can be some thrown from the external code. File not found exception seems like one that may come up often, so I would catch it and in the finally block gracefully close down anything I opened related to other code/processing and then notify the user and log it right there?
The only reason why you would want to catch an exception is for the finally part of the block to make sure that whatever you started before the exception is closed/finalized in a known state? But even then you would want to throw this exception after performing these tasks so the user is notified by the global exception handler, there is no point duplicating this code at this point?
So other than a global exception handler you would have try-catch-finally blocks for these scenarios.
So assuming that I am missing something here, there may be the possibility that you want to try and catch a specific type of exception and then do something with it. I cannot think of anything that you would want to do in the catch block though since the global one would log/notify the user and if you have an exception that usually means that there is no deal for the code to continue on.
Is there any easy way to know which exceptions will be thrown from which modules? I think the only way I have read is to read the MSDN or component suppliers documentation, other than that there is no way to know what exception you would be trying to catch if you were looking for a specific one (not sure why you would)
This question came up since in my application I had a section of code in a try-catch block, and it ended up that when an exception occurred it was either because an object was null, or a string was invalid. Once I wrote code to handle those scenarios the try-catch block is no longer needed, if an exception is encountered now there is nothing the code can do to recover so it should be logged and let the user know so it can be fixed.
But this goes against what I have been reading and what has been preached to me, bad code is code with no try-catch blocks. So how does this all tie together and what piece am I missing here?
The first part of your question is all correct: you should only catch exceptions that you know how to handle. Otherwise, just let them bubble up until they reach code that can handle them.
(Note that "handle" doesn't mean "log" or "display an error". It means to correct the problem that caused the exception, or work around it in some way.)
If they never encounter code that can handle them, or if they are unhandlable exceptions (like OutOfMemory), then they will eventually reach the global unhandled exception handler. This is where you will log the exception (if appropriate), display a generic error to the user (if appropriate), and more often than not, terminate the application. You cannot simply continue as if nothing happened—the exception indicates that the application is in an unexpected state. If you try and continue, you're just going to crash, or worse.
I think there are some that I am missing, like when dealing with files there can be some thrown from the external code. File not found exception seems like one that may come up often, so I would catch it and in the finally block gracefully close down anything I opened related to other code/processing and then notify the user and log it right there?
FileNotFound is a good example of an exception that you will want to handle locally. In the same method (or perhaps one level up, in your UI code) that attempts to load the file, you'll have a catch block for FileNotFound exceptions. If appropriate, display a friendly error message to the user and ask them to choose another file. If it's internal code, give up and try something else. Whatever you need to do. There are few good reasons for FileNotFound to bubble up outside of your code.
This is sort of like using exceptions for flow control, but unavoidable. There is no way to avoid using exceptions (or error codes) for I/O, so you just need to handle the failure case. You could try and verify that the file exists first, before trying to open it, but that would not solve the race issue wherein the file gets deleted or becomes otherwise inaccessible between the time your verification code runs and when you actually try and open it. So now all you've done is duplicated your error-handling code in two places, which serves little purpose.
You have to handle exceptions like FileNotFound locally. The further away from the code that throws, the less likely you can do anything reasonable about it.
Another good example of this, aside from I/O-related exceptions, is a NotSupportedException. For example, if you try to call a method that isn't supported, you might get this exception. You will likely want to handle it and have code in the catch block that falls back to a safe alternative.
The only reason why you would want to catch an exception is for the finally part of the block to make sure that whatever you started before the exception is closed/finalized in a known state? But even then you would want to throw this exception after performing these tasks so the user is notified by the global exception handler, there is no point duplicating this code at this point?
This does not require catching the exception. You can have a try block with only a finally block. A catch block is not required. In fact, this is precisely what using statement implements. If you have state that needs to be cleaned up in the event of an exception being thrown, you should implement the IDisposable pattern and wrap usage of that object in a using block.
Is there any easy way to know which exceptions will be thrown from which modules? I think the only way I have read is to read the MSDN or component suppliers documentation, other than that there is no way to know what exception you would be trying to catch if you were looking for a specific one (not sure why you would)
Precisely. This is not really a problem, though, since you are only catching the exceptions that you can do something about. If you don't know that a module can throw a particular exception, you obviously can't have written code that can handle that exception.
The documentation will tell you all of the important exceptions that you might need to handle, like FileNotFound, SecurityException, or what have you.
This question came up since in my application I had a section of code in a try-catch block, and it ended up that when an exception occurred it was either because an object was null, or a string was invalid. Once I wrote code to handle those scenarios the try-catch block is no longer needed, if an exception is encountered now there is nothing the code can do to recover so it should be logged and let the user know so it can be fixed.
Avoiding exceptions in the first place is always the best option. For example, if you can design your application so that a null object or invalid string is impossible, great. That is what we call robust code. In that case, you don't need to catch these exceptions because there's no way that you can handle it. You thought you already handled the problem, so if an exception is getting thrown anyway, it is a sign of a bug. Don't gloss over it with a catch block.
But sometimes, catch blocks are still necessary, and you write code inside of the catch block to handle the problem. In that case, there's probably no reason to re-throw the exception or log it, so you don't have any code duplication.
But this goes against what I have been reading and what has been preached to me, bad code is code with no try-catch blocks. So how does this all tie together and what piece am I missing here?
Completely wrong. I don't know where you've been reading that, but it is nonsense. Exceptions are exceptional conditions. If your code has catch blocks strewn all over it, that is a sign that you are doing it wrong. Either you're using exceptions for flow control, you're swallowing exceptions in a misguided attempt to "improve reliability", or you don't know about the global unhandled exception handler.
Doesn't sound like you're missing anything to me.
The only thing I feel compelled to mention that doesn't fit strictly into any of your questions is that sometimes you might want to catch an exception and rethrow it as a different exception. The most common situation where you would do this is if you were designing a library of re-usable code. Inside of the library, you might catch internal exceptions and, if you cannot handle them, rethrow them as general exceptions. The whole point of a library is encapsulation, so you shouldn't let exceptions bubble up that the caller cannot possibly do anything about.
There is no true guide for exceptions management (raising and handling). Every app has to decide what level of flow control should be used and how exception has to be raised/handled.
General rules are:
exceptions are raised in exceptional situations
handle exception you can handle and do meaningful things for your app so
exception raising can be used in flow control, actually it's the only way you can reliably handle flow control when you are dealing with devices, so hardware interrupts. (printers, bill validators, file transfer...)
The rest is up to you. The meaning of exception management is made by you.
Imagine you need to download some files from an FTP server, one you don't control. Of course you can't trust other people so you need to prepare for temporary outages and such. So you wrap your downloading code in a try-catch-block and look for WebException if you catch one you might check for FtpStatusCode.ActionNotTakenFileUnavailableOrBusy if that was the error you simply retry. Similarly if you call a web service a 404 might be trouble, but a 429 means that you wait a little and retry, because you had been rate-limited.
Usually you can know which exceptions can be thrown by experience or documentation but C# lacks checked exceptions. Things like NullPointerException or ArgumentNullException can be properly handled with guards in your code. But other things, like errors external dependencies can sometimes be caught and handled by you without crashing the application.
I have read several times that using
catch (Exception ex)
{
Logger.LogError(ex);
}
without re throwing is wrong, because you may be hiding exceptions that you don't know about from the rest of the code.
However, I am writing a WCF service and am finding myself doing this in several places in order to ensure that the service does not crash. (SOA states that clients should not know or care about internal service errors since they unaware of the service implementation)
For instance, my service reads data from the file system. Since the file system is unpredictable I am trapping all exceptions from the read code. This might be due to bad data, permission problems, missing files etc etc. The client doesn't care, it just gets a "Data not available" response and the real reason is logged in the service log. I don't care either, I just know there was a problem reading and I don't want to crash.
Now I can understand there may be exceptions thrown unrelated to the file system. eg. maybe I'm out of memory and trying to create a read buffer has thrown an exception. The fact remains however, that the memory problem is still related to the read. I tried to read and was unable to. Maybe there is still enough memory around for the rest of the service to run. Do I rethrow the memory exception and crash the service even though it won't cause a problem for anything else?
I do appreciate the general idea of only catching exceptions you can deal with, but surely if you have an independent piece of code that can fail without affecting anything else, then it's ok to trap any errors generated by that code? Surely it's no different from having an app wide exception handler?
EDIT: To clarify, the catch is not empty, the exception is logged. Bad example code by me, sorry. Have changed now.
I wouldn't say that your service works as expected if there are permission problems on the disk. imho a service returning "Data not available" is even worse than a service returning "Error".
imagine that you are the user of your service. You make a call to it and it returns "No data". You know that you're call is correct, but since you don't get any data you'll assume that the problem is yours and go back investigating. Lots of hours can be spent in this way.
Which is better? Treating the error as an error, or lie to your users?
Update
What the error depends on doesn't really matter. Access problems should be dealt with. A disk that fails sometimes should be mirrored etc etc. SOA puts more responsibilities on you as a developer. Hiding errors doesn't make them go away.
SOA should pass errors. It may not be a detailed error, but it should be enough for the client to understand that the server had a problem. Based on that, the client may try again later on, or just log the error or inform the service desk that a manual action might need to be taken.
If you return "No data", you won't give your users a chance to treat the error as they see fit.
Update2
I do use catch all in my top level. I log exceptions to the event log (which is being monitored).
Your original question didn't have anything in the catch (which it do now). It's fine as long as you remember to monitor that log (so that you can correct those errors).
If you are going to adopt this strategy you are going to make it very hard for deployment teams to work out why the client fails to work. At the minimum log something somewhere.
One of the main issues becomes that you will never know that something went wrong. It isn't only your clients / consumers that have the error hidden from them, it is you as the service developer yourself.
There's absolutely no problem with that code. Make sure the user gets a nice message, like "Data not available due to an internal problem. The issue has been logged and the problem will be dealt with." And everybody's fine.
It's only a problem if you eat and swallow the exception so that nobody in the world will ever fix it.
Exceptions need always to be dealt with, either by writing special code or by just fixing the path that results in the exception. You can't always anticipate all errors, but you can commit to fixing them as soon as you become aware of them.
I believe the idea is to prevent missing errors. Consider this: The service returns fine but is not doing as expected. You have to go and search through event logs, file logs etc. to find a potential error. If you put a trace write in there, you can identify hopefully the cause, but likely the area of hte issue and a timestamp to correlate errors with other logs.
If you use .NET Trace, you can implement in code and not turn it on until required. Then to debug you can turn it on without having to recompile code.
WCF Services can use FaultException to pass exceptions back to the client. I have found this useful when building a WCF n-tier application server.
It's commendable to ensure that your service does not crash, in a production environment. When debugging, you need the application to crash, for obvious reasons.
However, from your explanations, I get the impression that you're catching the exceptions you expect to be thrown, and catch the rest with an empty catch block, meaning you'll never know what happened.
It's correct to catch all exceptions as a last resort, but please log those too, they are no less interesting than those you expected. After catching and logging all exceptions related to network, I/O, security, authentication, timeout, bad data, whatever, log the rest.
In general you can say that every exception occurs in a specific circumstance. For debugging purposes it is usefull to have as much information as possible about the failure so the person who is about to fix the bug know where to look and can fix the code in a minimum amount of time, which save his boss some money.
Besides that, throwing and catching specific exceptions will make your code more readable/understable and easier to maintain. Catching a general exception will fail on this point in every point of view. Therefore, also make sure that, when throwing an exception, that is is well documented (e.g. in XML comments so the caller knows the method can throw the specific exception) and has a clear name on what went wrong. Also include only information in the exception that is directly related to the problem (like id's and such).
In vb.net, a somewhat better approach would be "Catch Ex As Exception When Not IsEvilException(Ex)", where "IsEvilException" is a Boolean function which checks whether Ex is something like OutOfMemoryException, ExecutionEngineException, etc. The semantics of catching and rethrowing an exception are somewhat different from the semantics of leaving an exception uncaught; if a particular "catch" statement would do nothing with the exception except rethrow "as is", it would be better not to catch it in the first place.
Since C# does not allow exception filtering, you're probably stuck with a few not-very-nice choices:
Explicitly catch and rethrow any "evil" types of exceptions, and then use a blanket catch for the rest
Catch all exceptions, rethrow all the evil ones "as-is", and then have your logic handle the rest
Catch all exceptions and have your logic handle them without regard for the evil ones, figuring that if the CPU is on fire it will cause enough other exceptions to be raised elsewhere to bring the program down before persistent data gets corrupted.
One problem with exception handling in both Java and .net is that it binds tightly three concepts which are actually somewhat orthogonal:
What condition or action triggered the exception
Should the exception be acted upon
Should the exception be considered resolved
Note that sometimes an exception will involve two or more types of state corruption (e.g. an attempt was made to update an object from information at a stream, and something goes wrong reading the stream, leaving both the stream and the object being updated in bad states). Code to handle either condition should act upon the exception, but the exception shouldn't be considered resolved until code for both has been run. Unfortunately, there is no standard pattern for coding such behavior. One could add a virtual read-only "Resolved" property to any custom exceptions one implements, and rethrow any such exceptions if "Resolved" returns false, but no existing exceptions will support such a property.
If something is wrong, then it is wrong. It should crash.
You can never assure proper operations if something is crashing in the code. Even if that means that a page/form will always crash as soon as it is visited, you can never assure that things will keep working, or any changes be functionally committed.
And if a data resource crashes and instead returns a resource with 0 entries, the user will just be incredibly confused by something not returning any results when there should be obvious results. Valueable time will be spent by the user trying to find out what (s)he did wrong.
The only times I would recommend catching all exceptions (and logging them, not ignoring them), is if the code that is being ran is from plugins/compiled code from users, or some weird COM library, that you have no control over yourself.
First, I'm already familiar with the simple exception handling syntax but I'm asking about the best place, the best time and the best way to deal with them.
I'm building an N-Layered application. so I think the DAL will sometime generate some errors to handle .. and I just learned about the SqlException class, what's the deal with that class ? I once saw a code that handles the SqlException then it handles Exception!
After knowing the practice and where I'm going to handle them, I'm planning to create a method to connect to the database and log the errors in a database so I could fix it but still I don't know what information should I collect to allow me identify the whole situation!
I thought exceptions handling was not a big deal. but every now and then I read some strange advices -that I never understood- on the questions comments but no one could answer me since it was some very old questions!
"Don't just explicitly catch
exceptions"
"the code that is used by
higher-layers in your application must
always only throw exceptions and never
worry about how to deal with them."
EDIT
What about Page_Error event and Application_Error .. I saw that they are a good practice for handling errors
Exception handling is a big deal, and it's not simple to design a good strategy for that.
First of all, some general rules:
Exceptions occur when the running code is completely unable to go ahead, so maybe it tried to handle some internal exceptions but ultimately failed. Think about TCP connection: if a damaged packet arrives, it's an exception, but TCP protocol can handle it. If too many are damaged, an I/O or socket exception is thrown
Exceptions can not always be handled. In almost all cases, when you get an exception from underlying layers you are unable to run corrective code. If your application depends on a DB and that is offline, when you get the exception about it you can only display an error message
Exceptions can be unexpected, and can reveal design or implementation flaws. For example, an implementation flaw can be the situation in which you have a redundant DB but when you fail to connect to frist mirror you don't try with the second
For the third point, it's important to log exceptions and periodically analyse logs to find any weird situation. So, let's begin with the concrete answer.
First of all
think about "handling" the exception. When you write every single code line, think about the possible problems that may prevent it from completing, and think about the possible corrective actions. if any are possible. An error message is not a good handling way, it's the latest strategy.
Don't start to write try-catch(Exception), but prefer specific exceptions. If you need to parse strings to numbers etc, then expect FormatException, if you need to cast from Object to your type expect InvalidCastException
When you write lower-level layers
don't hesitate to throw exceptions!! Don't do like many folks do, ie. return null or use (like ANSI C) a boolean return value and reference parameters. Exceptions are there for that. If you can handle an exception (ie. you don't find a local file but you know you have a remote backup, so handle FileNotFoundException by calling the remote mirror, but if you can't still connect then ultimately throw) then do it and try to resume computation, but if you cannot then throw. And don't forget to throw the inner exception, if present, because it is helpful for logging in the highest layer.
Basically, you can still decide to throw an exception on your own even if you don't catch any! And this is highly recommended especially when function parameters are invalid!
Another good option is to still log in the underlying layers. You actually want to log no matter an exception occurs.
When you log
remember to give an adequate severity to the messages. If you find via code that your DB is offline, that's not an unexpected exception. Still log it as an error, but don't worry about code bugs when you investigate the logs. Instead, if you catch an exception that your code is unable to recognize (a NullReferenceException is a classic example) then log with highest severity, ie. fatal, to give it maximum priority!
A good strategy for ASP.NET
can surely be based upon Page.OnError method. If you have a base page class for all of the pages of your site, you should definitely override that method. In that method, you should first log your exception.
You also shouldn't abuse of try-catch(Exception) blocks, because if you don't catch an exception you can't handle with catch, you will have to handle it via OnError.
When you run such a method, don't immediately think about Server.RemoveError(). You can prefer to have a static HTML page for HTTP 500 error (that is triggered when an unhandled exception bubbles to ASP.NET runtime) that displays a courtesy message to the user.
Briefly
Don't hesitate to throw in underlying layers if anything strange occurs
As said by your advice, don't handle exceptions you are unable to handle (if you catch an exception you can't handle, rethrow it)
LOG!!!!!!!!!!!!!!!!!
Don't disclose exception details to final users on a public website, never!! By default, ASP.NET prevents that from occurring, but you could still use OnError to print stack trace
Use OnError, or Application_Error as single central point to handle all unexpected exceptions
Periodically examine logs against error/fatal messages to find issues with your code, then think about maintaining/debugging/fixing it
Take a look at elmah. It's a logger for asp.net. Renders all errors on a nice summary page.
http://code.google.com/p/elmah/
The best way to handle exceptions is in the specific layer they apply to. If it is a constraint volation, for example, 2 users with the same name, you should let that bubble up to the UI and alert the user.
Same goes with any business rule violations. Those should bubble up to the UI so the end user knows what went wrong.
A SQL Connectivity error is best handled in the DAL...etc..
The how/when/where to catch exceptions may depend on what your trying to do exactly, its difficult to give an exact catch all always correct answer.
As to your specific questions,
I just learned about the SqlException
class, what's the deal with that class
? I once saw a code that handles the
SqlException then it handles
Exception!
Its good practice to handle the specific exception you believe may occur, if your not sure what type this exception is you can just 'Exception', if you want something specific to occur on a 'SQLException' and something else to happen with an 'Exception' then there is certainly nothing wrong with writing code that handles both.
"Don't just explicitly catch
exceptions"
I believe this is refering to code like this
try
{
int i = 1/0;
}
catch(Exception e)
{
//do nothing
}
This exception will be caught but you'll never know it happened, hence this is not a good idea, and the person using the code will be scratching their head as to whats going on.
I think what you are asking here is a Error/Exception Handling Strategy for any application.
I think it includes:
Where - All places where you think an exception can occur or which need more monitoring like DB calls, External Service Calls, Use of Arrays, User Input Parsing, Type Casting and so on...
How - All you high level layers should throw the exception and it should be captured at the entry point and processed to understand the root cause. Usually you do this in Application_Error() where you catch the exception and log it for troubleshooting. How you log an exception is upto you. A Log File or DB driven log is an option based on your requirements and available resources.
IMO apart from extremely rare circumstances I only ever use exception handling for I/O related code where there are interactions with services and file systems whose functionality and maintenance is beyond the control of my applications.
I have always considered the use try/catch statements to manipulate the logic (flow-of-control) in a program in the same way if/else statement work to be extremely bad practice. Most common exceptions can be avoided if you use the tools at hand correctly.
I’m used to having try/catch blocks in every method. The reason for this is so that I can catch every exception at the point of infraction and log it. I understand, from my reading and conversations with others, that this isn’t a popular view. One should only catch what one is prepared to handle. However, if I don’t catch at the point of infraction, then it would be possible to never log that infraction and know about it. Note: When I do catch and don’t handle, I still throw. This allows me to let the exception propagate to something that will handle it, yet still let me log it at the point of infraction.
So... How does one avoid try/catch in every method, yet still log the error at the point at which it occurred?
No, don't catch everything. Exceptions propagate higher up on the stack. All you have to do is make sure that the exception is caught before it gets to the top of the stack.
This means, for instance, that you should surround the code of an event handler with a try/catch block. An event handler may be the "top of the stack". Same for a ThreadStart handler or a callback from an asynchronous method.
You also want to catch exceptions on layer boundaries, though in that case, you might just want to wrap the exception in a layer-specific exception.
In the case of ASP.NET, you may decide to allow ASP.NET Health Monitoring to log the exception for you.
But you certainly don't ever need to catch exceptions in every method. That's a major anti-pattern. I would loudly object to you checking in code with that kind of exception handling.
You can see everything at stack trace - no need to try/catch every method.
Stick to few rules:
Use try/catch only if you want to use a custom exception type
Define a new exception type only if upper levels needs to know that
Try/catch at top level instead of doing that for each method
OK, having read all the answers saying you should have a single try/catch at the top level, I'm going to weigh in with an alternative view.
I wouldn't put a try/catch in every method, far from it. But I would use a try/catch around sections of code that I expected to fail (e.g. opening a file), and where I wanted to add additional information to the exception (to be logged higher up the chain).
A stack trace saying and a message saying "permission denied" might be enough to allow you as a programmer to figure out what went wrong, but my goal is to provide the user with meaningful information, such as "Could not open file 'C:\lockedfile.txt'. Permission denied.".
As in:
private void DoSomethingWithFile(string filename)
{
// Note: try/catch doesn't need to surround the whole method...
if (File.Exists(filename))
{
try
{
// do something involving the file
}
catch (Exception ex)
{
throw new ApplicationException(string.Format("Cannot do something with file '{0}'.", filename), ex);
}
}
}
I'd also like to mention that even the people saying "only have one try/catch" would presumably still use try/finally throughout their code, since that's the only way to guarantee proper cleanup, etc.
Catching and rethrowing an exception that you cannot handle is nothing more than a waste of processor time. If you can't do anything with or about the exception, ignore it and let the caller respond to it.
If you want to log every exception, a global exception handler will do just fine. In .NET, the stack trace is an object; its properties can be inspected like any other. You can write the properties of the stack trace (even in string form) to your log of choice.
If you want to ensure that every exception is caught, a global exception handler should do the trick. In point of fact, no application should be without one.
Your catch blocks should only catch exceptions that you know that you can gracefully recover from. That is, if you can do something about it, catch it. Otherwise, let the caller worry about it. If no callers can do anything about it, let the global exception handler catch it, and log it.
I definitely don't use a try catch wrapper around every method (oddly enough, I did when I first started but that was before I learned better ways).
1) To prevent the program from crashing and the users losing their info, I do this
runProgram:
try
{
container.ShowDialog();
}
catch (Exception ex)
{
ExceptionManager.Publish(ex);
if (MessageBox.Show("A fatal error has occurred. Please save work and restart program. Would you like to try to continue?", "Fatal Error", MessageBoxButtons.YesNo) == DialogResult.Yes)
goto runProgram;
container.Close();
}
container is where my application starts so this basically puts a wrapper around my entire app so that nothing causes a crash that can't be recovered. This is one of those rare instances where I don't really mind using a goto (it is a small amount of code and still quite readable)
2) I only catch exceptions in methods where I expect something could go wrong (such as a timeout).
3) Just as a point of readibility, if you have a try catch block with a bunch of code in the try section and a bunch in the catch section, it is better to extract that code to a well named method.
public void delete(Page page)
{
try
{
deletePageAndAllReferences(page)
}
catch (Exception e)
{
logError(e);
}
}
To do it at the point of occurrence, you would still need a try/catch. But you don't necessarily need to catch the exceptions everywhere. They propagate up the call stack, and when they are caught, you get a stack trace. So if a problem emerges, you can always add more try/catches as needed.
Consider checking out one of the many logging frameworks that are available.
I don't think you need to catch everything at the point of infraction. You can bubble up your exceptions, and then use the StackTrace to figure out where the point of infraction actually occurred.
Also, if you need to have a try catch block, the best approach I've heard is to isolate it in a method, as to not clutter the code with huge try catch blocks. Also, make as few statements as possible in the try statement.
Of course, just to reiterate, bubbling up your exceptions to the top and logging the stacktrace is a better approach than nesting try-catch-log-throw blocks all throughout your code.
I would look into using ELMAH for exception handling, which is pretty much a concept of "let exceptions happen". ELMAH will take care of logging them and you can even set it to email you when exceptions for a certain project reach or exceed a specific threshold. In my department, we stay as far away from try/catch blocks as possible. If something is wrong in the application, we want to know right away what the issue is so we can fix it, instead of repressing the exception and handling it in code.
If an exception happens, that means that something isn't right. The idea is to make your application do only what it should do. If it's doing something different and causing exceptions, your response should be to fix the reason it's happening, not let it happen and handle it in code. This is just my/our philosophy and it's not for everyone. But we've all been burned way too many times by an application "eating" an exception for some reason or another and no one knows that something is wrong.
And never, ever, EVER catch a general Exception. Always, always, always catch the most specific exception so that if an exception is thrown, but it's not the type you're expecting, again, you'll know because the app will crash. If you just catch (Exception e), then no matter what type of exception is thrown, your catch block will now be responsible for responding to every single type of exception that could possibly be thrown. And if it doesn't, then you run into the whole "eating" exceptions, where something is going wrong but you never know until it is likely too late.
How does one avoid try/catch in every method, yet still log the error at the point at which it occurred?
It depends on the hosting env. Asp.Net, WinForms, and WPF all have different ways of capturing unhandled exceptions. But once the global handler is passes an exception instance you can determine the point of throw from the exception, as each exception includes a stacktrace.
Realistically, avoid granular try/catches. Allow the exception to traverse upwards in the stack and be caught in as high a level as possible. If you have a specific point of concern, then place logging in the immediate catch, if you are worried about the exception cascading - although you would still be able to resolve these by drilling into the inner exceptions.
Exception handling should not be an afterthought. Make sure that you do it consistently. I have seen a lot of people put a broad try/catch from the beginning to the end of every method and catch the general exception. People think that this helps them get more information, when in fact, it doesn't. More is less in some cases, as less is more. I never get tired of the axiom that "Exceptions should be used to note exceptional behavior." Recover if you can, and try to reduce the number of overall exceptions. Nothing is more frustrating when you are trying to troubleshoot an issue and seeing hundreds of the same NullReferenceException, or similar, when something goes wrong.
Exceptions are implemented so that they have no cost unless thrown.
This means to me that performance ramifications is not a strong argument against. Exceptional conditions usually are ... exceptional.