- All exceptions derive from
System.Exception
and therefore, they can be handled by a generic catch block.
- A generic catch is a catch block with no data type.
- They are rarely used because there is no way to capture any information about the exception.
- C# doesn’t support the ability to throw an exception of type object.
- It is preferable to include a catch block that is specific to the most derived type.
- Avoid using exception handling to deal with expected situations or normal control flow.
- Instead of relying on an exception to validate data entered by the user, provide a means of checking before attempting the conversion.
- Exceptions are designed specifically for tracking exceptional, unexpected, and potentially fatal situations.
- C# incurs a slight performance hit when throwing an exception, taking microseconds compared to the nanoseconds most operations take.
- The runtime has to search all outer catch blocks until it finds a matching block.
- When it doesn’t, has to look if a debugger is attached, it takes slightly more time.
- Use exception handling if the event doesn't occur very often, that is, if the event is truly exceptional and indicates an error.
- When you use exception handling, less code is executed in normal conditions.
- There are situations in which a finally block won’t run.
- For example, when the try block goes into an infinite loop, it will never exit the try block and never enter the finally block.
- In situations such as a power outage, no other code will run.
- Preventing the finally block from running can be achieved by using
Environment.FailFast()
.
- This method has two different overloads: one that takes a string and another one that takes an exception.
- The method writes the message/exception to the Windows application event log, and the application is terminated.
- It’s important to make sure that your finally block does not cause any exceptions.
- When this happens, control immediately leaves the finally block and moves to the next outer try block, if any.
- The original exception is lost and you can’t access it anymore.
- In catch blocks, always order exceptions from the most specific to the least specific.
- Catch only the exceptions that you can handle.
- For example, opening a file for exclusive read-write access may throw a
IOException
.
- Other exception types should be left for callers higher in the stack.
- Don’t hide (bury) exceptions you don’t fully handle.
- This may result in a critical system problem going undetected.
- Unless code takes explicit action to handle an exception or explicitly determines certain exceptions to be innocuous, catch blocks should re-throw exceptions instead of catching them and hiding them from the caller.
- Use
System.Exception
and general catch blocks rarely.
- All exceptions derive from
System.Exception
, even system level exceptions.
- These exceptions include
OutOfMemoryException
and StackOverflowException
.
- The best way to handle these
System.Exceptions
is to allow them to go unhandled or to gracefully shut down the application.
- These exceptions are runtime exceptions that the developer cannot write code to recover from.
- They were defaulted to nonrecoverable such that catching them without rethrowing them will cause the CLR to rethrow them anyway.
throw
- Use
throw
; rather than throw <exception object>
inside a catch block.
- Rethrowing an specific exception will reset the stack trace to the location of the rethrown call.
- Unless you are rethrowing with a different exception type or intentionally hiding the original call stack, use throw to allow the same exception to propagate up the call stack.
- When rethrowing different exceptions, to preserve the original exception set the new exception’s InnerException property.
- Rethrowing a different exception should be reserved for the following situations:
- Changing the exception type clarifies the problem.
- Private data is part of the original exception.
- The exception type is too specific for the caller to handle appropriately.
- Do not try to reuse exception object instances.
- Each time you throw an exception, create a new one.
- This is true especially when working in a multi-threaded environment, where the stack trace can be changed by another thread.
- An empty catch block generates a
catch(object)
block.
- This means that regardless of the type thrown, the empty catch block will catch it.
- It is not possible to explicitly declare a
catch(object)
exception block.
System.Exception
Properties
StackTrace
: A string that describes all the methods that are currently in execution.
- This gives you a way of tracking which method threw the exception and how that method was reached.