Determining exception type after the exception is caught?
You can actully determine type inside a catch(...), but it is not very useful:
#include <iostream>
#include <exception>
class E1 : public std::exception {};
class E2 : public std::exception {};
int main() {
try {
throw E2();
}
catch( ... ) {
try {
throw;
}
catch( const E1 & e ) {
std::cout << "E1\n";
}
catch( const E2 & e ) {
std::cout << "E2\n";
}
}
}
How to check which exception type was thrown in Java?
If you can, always use separate catch
blocks for individual exception types, there's no excuse to do otherwise:
} catch (NotAnInt e) {
// handling for NotAnInt
} catch (ParseError e) {
// handling for ParseError
}
...unless you need to share some steps in common and want to avoid additional methods for reasons of conciseness:
} catch (NotAnInt | ParseError e) {
// a step or two in common to both cases
if (e instanceof NotAnInt) {
// handling for NotAnInt
} else {
// handling for ParseError
}
// potentially another step or two in common to both cases
}
however the steps in common could also be extracted to methods to avoid that if
-else
block:
} catch (NotAnInt e) {
inCommon1(e);
// handling for NotAnInt
inCommon2(e);
} catch (ParseError e) {
inCommon1(e);
// handling for ParseError
inCommon2(e);
}
private void inCommon1(e) {
// several steps
// common to
// both cases
}
private void inCommon2(e) {
// several steps
// common to
// both cases
}
Identifying Exception Type in a handler Catch Block
UPDATED: assuming C# 6, the chances are that your case can be expressed as an exception filter. This is the ideal approach from a performance perspective assuming your requirement can be expressed in terms of it, e.g.:
try
{
}
catch ( Web2PDFException ex ) when ( ex.Code == 52 )
{
}
Assuming C# < 6, the most efficient is to catch a specific Exception
type and do handling based on that. Any catch-all handling can be done separately
try
{
}
catch ( Web2PDFException ex )
{
}
or
try
{
}
catch ( Web2PDFException ex )
{
}
catch ( Exception ex )
{
}
or (if you need to write a general handler - which is generally a bad idea, but if you're sure it's best for you, you're sure):
if( err is Web2PDFException)
{
}
or (in certain cases if you need to do some more complex type hierarchy stuff that cant be expressed with is
)
if( err.GetType().IsAssignableFrom(typeof(Web2PDFException)))
{
}
or switch to VB.NET or F# and use is
or Type.IsAssignableFrom
in Exception Filters
How do I determine what type of exception occurred?
The other answers all point out that you should not catch generic exceptions, but no one seems to want to tell you why, which is essential to understanding when you can break the "rule". Here is an explanation. Basically, it's so that you don't hide:
- the fact that an error occurred
- the specifics of the error that occurred (error hiding antipattern)
So as long as you take care to do none of those things, it's OK to catch the generic exception. For instance, you could provide information about the exception to the user another way, like:
- Present exceptions as dialogs in a GUI
- Transfer exceptions from a worker thread or process to the controlling thread or process in a multithreading or multiprocessing application
So how to catch the generic exception? There are several ways. If you just want the exception object, do it like this:
try:
someFunction()
except Exception as ex:
template = "An exception of type {0} occurred. Arguments:\n{1!r}"
message = template.format(type(ex).__name__, ex.args)
print message
Make sure message
is brought to the attention of the user in a hard-to-miss way! Printing it, as shown above, may not be enough if the message is buried in lots of other messages. Failing to get the users attention is tantamount to swallowing all exceptions, and if there's one impression you should have come away with after reading the answers on this page, it's that this is not a good thing. Ending the except block with a raise
statement will remedy the problem by transparently reraising the exception that was caught.
The difference between the above and using just except:
without any argument is twofold:
- A bare
except:
doesn't give you the exception object to inspect - The exceptions
SystemExit
,KeyboardInterrupt
andGeneratorExit
aren't caught by the above code, which is generally what you want. See the exception hierarchy.
If you also want the same stacktrace you get if you do not catch the exception, you can get that like this (still inside the except clause):
import traceback
print traceback.format_exc()
If you use the logging
module, you can print the exception to the log (along with a message) like this:
import logging
log = logging.getLogger()
log.exception("Message for you, sir!")
If you want to dig deeper and examine the stack, look at variables etc., use the post_mortem
function of the pdb
module inside the except block:
import pdb
pdb.post_mortem()
I've found this last method to be invaluable when hunting down bugs.
How to determine if an exception is of a particular type
before your current catch add the following:
catch(DbUpdateException ex)
{
if(ex.InnerException is UpdateException)
{
// do what you want with ex.InnerException...
}
}
From C# 6, you can do the following:
catch(DbUpdateException ex) when (ex.InnerException is UpdateException)
{
// do what you want with ex.InnerException...
}
Check for exception type inside Exception catch block and log it
The is
operator is performing a boolean operation on whether or not your exception can be converted to the target type, but that type conversion is not then passed to the first branch of your ternary.
You can either recast:
var bodyString = ex is JsonParsingException
? ((JsonParsingException)ex).GetUnderlyingByteArrayUnsafe()
: null;
Or you can use the as
operator which will attempt to make the conversion for you and if it cannot, will return null:
var jsonParsingException = ex as JsonParsingException;
var bodyString = jsonParsingException != null
? jsonParsingException.GetUnderlyingByteArrayUnsafe()
: null;
Note that with C#7 pattern matching, you can also output the result to a temporary local variable and enable a one-liner:
var bodyString = ex is JsonParsingException j
? j.GetUnderlyingByteArrayUnsafe()
: null;
and finally, @mjwills pointed out that you can wrap the as operation in braces and check for null with the null propagation operator, allowing for a one-liner as well:
var bodyString = (ex as JsonParsingException)?.GetUnderlyingByteArrayUnsafe();
Exception Handling for specifc exception type
Ideally you should handling each Exception individually like so:
try
{
}
catch (IOException ex)
{
// Log specific IO Exception
}
catch (NullReferenceException ex)
{
// Log Specific Null Reference Exception
}
catch (Exception ex)
{
// Catch everything else
}
You could do:
string exceptionErrorMessage;
try
{
}
catch (IOException ex)
{
// Log specific IO Exception
exceptionErrorMessage = ex.Message;
}
catch (NullReferenceException ex)
{
// Log Specific NullReferenceException
exceptionErrorMessage = ex.Message;
}
catch (Exception ex)
{
// Catch everything else
exceptionErrorMessage = ex.Message;
}
if (!string.IsNullOrEmpty(exceptionErrorMessage))
{
// use your logger to log exception.
Console.WriteLine(exceptionErrorMessage);
}
Here's the correct to OPs code using the same method he wanted:
try
{
}
catch (Exception e)
{
var exType = e.GetType().Name;
switch (exType)
{
case "IOException":
case "NullReferenceException":
Console.WriteLine(e.Message);
break;
}
}
Related Topics
How to Provider User with Autocomplete Suggestions for Given Boost::Spirit Grammar
Is Left-Shifting (<<) a Negative Integer Undefined Behavior in C++11
Copy Elision: Move Constructor Not Called When Using Ternary Expression in Return Statement
Order of Execution in Operator <<
Global Function Definition in Header File - How to Avoid Duplicated Symbol Linkage Error
G++ Variable Size Array No Warning
C++ Using Class Method as a Function Pointer Type
C++ Templates Angle Brackets Pitfall - What Is the C++11 Fix
Do I Need an Extern "C" Block to Include Standard Posix C Headers
C++ Static Template Member, One Instance for Each Template Type
Boost Zip_Iterator and Std::Sort
For Purposes of Ordering, Is Atomic Read-Modify-Write One Operation or Two
What Is a Reference-To-Pointer
How to Make My Split Work Only on One Real Line and Be Capable to Skip Quoted Parts of String
Integer Division Rounding with Negatives in C++
Std::Ostringstream Printing the Address of the C-String Instead of Its Content
Treating Memory Returned by Operator New(Sizeof(T) * N) as an Array
How to Set Visual Studio Filters for Nested Sub Directory Using Cmake