Can following code be considered as a good practice? If not, why?
try
{
// code that can cause various exceptions.
The main thing it depends on is where your are catching the exception. In general libraries should be more conservative with catching exceptions whereas at the top level of your program (e.g. in your main method or in the top of the action method in a controller, etc) you can be more liberal with what you catch.
The reason for this is that e.g. you don't want to catch all exceptions in a library because you may mask problems that have nothing to do with your library, like "OutOfMemoryException" which you really would prefer bubbles up so that the user can be notified, etc. On the other hand, if you are talking about catching exceptions inside your main() method which catches the exception, displays it and then exits... well, it's probably safe to catch just about any exception here.
The most important rule about catching all exceptions is that you should never just swallow all exceptions silently... e.g. something like this in Java:
try {
something();
}
catch (Exception ex) {}
or this in Python:
try:
something()
except:
pass
Because these can be some of the hardest issues to track down.
A good rule of thumb is that you should only catch exceptions that you can properly deal with yourself. If you cannot handle the exception completely then you should let it bubble up to someone who can
Short answer: Don't do this unless there is some reason that you must. Instead, catch specific exceptions you can deal with at the point you can deal with them, and allow all other exceptions to bubble up the stack.
TL;DR answer: It depends what you're writing, what is going to be calling your code, and why you feel that you need to introduce a custom exception type.
The most important question to ask, I think, is if I catch, what benefit does my caller get?
Imagine you're processing a low-level data source; maybe you're doing some encoding or deserialisation. Our system is nice and modular, so you don't have much information about what your low-level data source is, or how your code is being called. Maybe your library is deployed on a server listening to a message queue and writing data to disk. Maybe it's on a desktop and the data is coming from the network and being displayed on a screen.
There are lots of varied exceptions that might occur (DbException, IOException, RemoteException, etc), and you have no useful means of handling them.
In this situation, in C#, the generally accepted thing to do is let the exception bubble up. Your caller knows what to do: the desktop client can alert the user to check their network connection, the service can write to a log and allow new messages to queue up.
If you wrap the exception in your own MyAwesomeLibraryException, you've made your caller's job harder. Your caller now needs to:-
Make sure that extra effort is worth their time. Don't do it for no reason!
If the main justification for your custom exception type is so that you can provide a user with friendly error messages, you should be wary of being overly-nonspecific in the exceptions you catch. I've lost count of the number of times - both as a user and as an engineer - that an overzealous catch statement has hidden the true cause of an issue:-
try
{
GetDataFromNetwork("htt[://www.foo.com"); // FormatException?
GetDataFromNetwork(uriArray[0]); // ArrayIndexOutOfBounds?
GetDataFromNetwork(null); // ArgumentNull?
}
catch(Exception e)
{
throw new WeClearlyKnowBetterException(
"Hey, there's something wrong with your network!", e);
}
or, another example:-
try
{
ImportDataFromDisk("C:\ThisFileDoesNotExist.bar"); // FileNotFound?
ImportDataFromDisk("C:\BobsPrivateFiles\Foo.bar"); // UnauthorizedAccess?
ImportDataFromDisk("C:\NotInYourFormat.baz"); // InvalidOperation?
ImportDataFromDisk("C:\EncryptedWithWrongKey.bar"); // CryptographicException?
}
catch(Exception e)
{
throw new NotHelpfulException(
"Couldn't load data!", e); // So how do I *fix* it?
}
Now our caller has to unwrap our custom exception in order to tell the user what's actually gone wrong. In these cases, we've asked our caller to do extra work for no benefit. It is not intrinsically a good idea to introduce a custom exception type wrapping all exceptions. In general, I:-
Catch the most specific exception I can
At the point I can do something about it
Otherwise, I just let the exception bubble up
Bear in mind that hiding the details of what went wrong isn't often useful
That doesn't mean you should never do this!
Sometimes Exception
is the most specific exception you can catch because you want to handle all exceptions in the same way - e.g. Log(e); Environment.FailFast();
Sometimes you have the context to handle an exception right at the point where it gets thrown - e.g. you just tried to connect to a network resource and you want to retry
Sometimes the nature of your caller means that you cannot allow an exception to bubble up - e.g. you're writing logging code and you don't want a logging failure to "replace" the original exception that you're trying to log!
Sometimes there's useful extra information you can give your caller at the point an exception is thrown that won't be available higher up the call stack - e.g. in my second example above we could catch (InvalidOperationException e)
and include the path of the file we were working with.
Occasionally what went wrong isn't as important as where it went wrong. It might be useful to distinguish a FooModuleException
from a BarModuleException
irrespective of what the actual problem is - e.g. if there's some async going on that might otherwise prevent you usefully interrogating a stack trace.
Although this is a C# question, it's worth noting that in some other languages (particularly Java) you might be forced to wrap because checked exceptions form part of a method's contract - e.g. if you're implementing an interface, and the interface doesn't specify that the method can throw IOException.
This is all pretty general stuff, though. More specifically to your situation: why do you feel you need the custom exception type? If we know that, we can maybe give you some better tailored advice.