Recently I got got an exception that I wasn't expecting because it wasn't documented in MSDN that it can be thrown by the particular constructor. So here is the C# line that threw exception:
using (StreamReader sr = new StreamReader(filePath))
filePath here is the string that should contain full path to a certain file. The problem was that my "filePath" variable was actually a path to the folder and not to the file. Because of this the constructor StreamReader(filePath) threw:
System.UnauthorizedAccessException: Access to the path 'D:\testFolder' is denied.
Ok so this was obviously a bug and I've fixed it by passing a correct path... but looking at the MSDN docs for StreamReader(string) I don't see any mentioning of this exception. Under exception section there are:
Thinking some more about this issue, I guess the exception thrown should actually be IOException and not UnauthorizedAccessException. Is this a bug in .NET Framework? The problem is that I had IOException handler in place that notifies user about invalid file path and continues application workflow without crashing. This UnauthorizedAccessException crashed my application because it was unhandled.
How should I deal with this kind of issues? I think I encounter similar problem of undocumented exceptions in the past but this one really motivated me to research this issue and ask question here.
The order of catch statements is important. Put catch blocks targeted to specific exceptions before a general exception catch block or the compiler might issue an error. The proper catch block is determined by matching the type of the exception to the name of the exception specified in the catch block.
You can put a try catch inside the catch block, or you can simply throw the exception again. Its better to have finally block with your try catch so that even if an exception occurs in the catch block, finally block code gets executed. Finally block may not get executed in certain exceptions.
Yes, throwing an exception causes the method to return immediately. However, it's not a normal return. For example, there is no return value. The only way to capture control from a method that is returning as a result of an exception being thrown, is to have an exception handler.
You can handle default errors at the application level either by modifying your application's configuration or by adding an Application_Error handler in the Global. asax file of your application. You can handle default errors and HTTP errors by adding a customErrors section to the Web. config file.
Unfortunately there is really no way to deal with this problem in a general fashion. The nature of C# and the CLR makes it difficult, if not outright impossible, to determine the full set of exceptions that can be thrown from a method. There are some simple APIs where it is possible but generally speaking its not.
The way I handle this is to simply catch Exception
. Recent versions of the CLR make it impossible to catch dangerous exceptions by default. Hence you're only going to be catching safer exceptions. Unless you want to react to a very specific fault just catch all and take the appropriate action for the API call failing
Although you cannot before hand be 100% aware of which types of exceptions a method can throw, there are ways to avoid falling pray to this issue, which is indeed something missing from the CLR, you follow a common pattern, which is to catch all exceptions derived from Exception
, and then further discriminate which you can handle and which you cannot,
try
{
}
catch (FileNotFoundException)
{
}
catch (DirectoryNotFoundException)
{
}
catch (IOException)
{
}
catch (Exception exception)
{
// For the ones you do not know how to handle, at least document it and throw
log(exception);
throw;
}
It will make your debugging a lot easier.
Do realize that this pattern will go base on hierarchy, where the more derived exception types should go first, or you risk the less derived catch
being executed first. In other words don't do this,
try
{
}
catch (IOException)
{
// Will get executed for both DirectoryNotFoundException and
// FileNotFoundException even though you specified specific ways to
// handle these types
}
catch (DirectoryNotFoundException)
{
}
catch (FileNotFoundException)
{
}
Alternatively, you could catch only Exception
and use an if
to test for the actual type, which isn't as pretty, but might be more flexible,
try
{
}
catch (Exception exception)
{
if (exception.GetType() == typeof(IOException))
{
}
else if (exception.GetType() == typeof(DirectoryNotFoundException))
{
}
else if (exception.GetType() == typeof(FileNotFoundException))
{
}
else
{
log(exception);
throw;
}
}
I don't think there is anyway to see all of the possible exceptions that could be thrown by a method. The fact of the matter is, you would have to recurse through all method calls to obtain that list and that just isn't going to happen.
Personally my feelings on exception handling are more along the lines of Joel Spolsky (http://www.joelonsoftware.com/items/2003/10/13.html); I rarely catch specific exceptions and I try to avoid using try-catch as much as is reasonably possible. In this case, I would be using catch (Exception e)
to avoid this problem then I would use an if-else to handle different types as appropriately as possible.
I read this before... may it will give you some insight. Microsoft Program Manager wrote this in a blog.
There are various scenarios where microsoft gives incorrect exceptions or exceptions which are not mentioned in msdn for certain method. I also faced similar situation where I have to catch General Exception in place of specific exception(system.formatexception in my case).
But then you can face issues like, avoiding static FxCop violation. According to fxcop one should not catch general exception.
We found the reason why we are getting wrong exception type and it was Exception inside another exception causing the real exception to evade.
**Getting exception is like getting pain in body. Both tells that there is issue in the system but taking same medicine for all pains is not good so try to catch specific exception in this case.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With