An exception is an indication of a problem that occurs during a program’s execution.
Exception handling enables you to create apps that can resolve (or handle) exceptions.
An exception is thrown when a method or the CLR detects a problem and is unable to handle it.
A stack trace includes the name of the exception in a descriptive message that indicates the problem that occurred and the complete method-call stack at the time the exception occurred.
Division by zero is not allowed in integer arithmetic.
Division by zero is allowed with floating-point values. Such a calculation results in the value infinity, which is represented by Double.PositiveInfinity
or Double.NegativeInfinity
, depending on whether the numerator is positive or negative. If both the numerator and denominator are zero, the result of the calculation is Double.NaN
.
When division by zero occurs in integer arithmetic, a DivideByZeroException
is thrown.
A FormatException
occurs when int.Parse
receives a string
that does not represent a valid integer.
try
BlockA try
block encloses the code that might throw exceptions, as well as the code that should not execute if an exception occurs.
A catch
block can specify an identifier representing the exception that the catch
block can handle. A general catch
clause catches all exception types, but cannot access exception information.
At least one catch
block and/or a finally
block must immediately follow the try
block.
An uncaught exception is an exception that occurs for which there’s no matching catch
block.
After an exception is handled, program control does not return to the throw point, because the try
block has exited. Instead, control resumes after the try
statement’s last catch
block. This is known as the termination model of exception handling.
When a method called in a program detects an exception, or when the CLR detects a problem, the method or the CLR throws an exception.
The point in the program at which an exception occurs is called the throw point.
If an exception occurs in a try
block, the try
block terminates immediately, and program control transfers to the first of the following catch
blocks in which the exception parameter’s type matches the type of the thrown exception.
The try
block and its corresponding catch
and finally
blocks together form a try
statement.
The CLR locates the matching catch
by comparing the thrown exception’s type to each catch
’s exception-parameter type. A match occurs if the types are identical or if the thrown exception’s type is a derived class of the exception-parameter type.
Once an exception is matched to a catch
block, the other catch
blocks are ignored.
Exception
HierarchyThe C# exception-handling mechanism allows objects only of class Exception
and its derived classes to be thrown and caught.
Class Exception
of namespace System
is the base class of the .NET Framework Class Library exception class hierarchy.
SystemException
The CLR generates SystemExceptions
, which can occur at any point during the execution of the program. Many of these exceptions can be avoided if apps are coded properly.
A benefit of using the exception class hierarchy is that a catch
block can catch exceptions of a particular type or—because of the is-a relationship of inheritance—can use a base-class type to catch exceptions in a hierarchy of related exception types.
A catch
block that specifies an exception parameter of type Exception
can catch all exceptions that derive from Exception
, because Exception
is the base class of all exception classes.
finally
BlockThe most common type of resource leak is a memory leak.
A memory leak occurs when a program allocates memory but does not deallocate it when it’s no longer needed. Normally, this is not an issue in C#, because the CLR performs garbage collection of memory that’s no longer needed by an executing program.
finally
BlockC#’s exception-handling mechanism provides the finally
block, which is guaranteed to execute if program control enters the corresponding try
block.
The finally
block executes regardless of whether the corresponding try
block executes successfully or an exception occurs. This makes the finally
block an ideal location in which to place resource-release code for resources acquired and manipulated in the corresponding try
block.
If a try
block executes successfully, the finally
block executes immediately after the try
block terminates. If an exception occurs in the try
block, the finally
block executes immediately after the matching catch
block (if any) completes.
If the exception is not caught by a catch
block associated with the try
block, or if a catch
block associated with the try
block throws an exception, the finally
block executes before the exception is processed by the next enclosing try
block (if there is one).
A throw
statement can rethrow an exception, indicating that a catch
block performed partial processing of the exception and now is throwing the exception again for further processing.
using
StatementThe using
statement simplifies writing code in which you obtain an IDisposable
resource, use the resource in a try
block and release the resource in a corresponding finally
block.
Exception
PropertiesProperty Message
of class Exception
stores the error message associated with an Exception
object.
Property StackTrace
of class Exception
contains a string
that represents the method-call stack.
InnerException
Another Exception
property used frequently by class library programmers is InnerException
. Typically, you use this property to “wrap” exception objects caught in your code, so that you then can throw new exception types specific to your libraries.
Exception
Properties and Stack UnwindingWhen an exception is thrown but not caught in a particular scope, stack unwinding occurs and an attempt is made to catch the exception in the next outer try
block.
User-defined exception classes should derive directly or indirectly from class Exception
of namespace System
.
User-defined exceptions should typically extend Exception
, have a class name that ends with “Exception” and define a parameterless constructor, a constructor that receives a string
argument (the error message), and a constructor that receives a string
argument and an Exception
argument (the error message and the inner-exception object).
?.
)C# 6’s new null-conditional operator (?.
) accesses a property or calls a method only if its left operand is not null
; otherwise, evaluation of the expression terminates and the value of the entire expression is null
.
A nullable type is a value type that also can be null
.
You specify a nullable type by following a value type’s name with a question mark (?
).
The GetValueOrDefault
method checks whether a nullable-type variable contains a value. If so, the method returns that value; otherwise, it returns the value type’s default value.
The HasValue
property returns true
if a nullable-type variable contains a value; otherwise, it returns false
.
The Value
property returns the nullable-type variable’s underlying value.
??
)The null coalescing operator (??
) has two operands. If the left operand is not null
, the entire ??
expression evaluates to the left operand’s value; otherwise, it evaluates to the right operand’s value.
when
ClausePrior to C# 6, you could catch an exception based only on its type.
C# 6 introduces exception filters that enable you to catch an exception based on a catch
’s exception type and a condition that’s specified with a when
clause.
You also can specify an exception filter for a general catch
clause that does not provide an exception type.
A catch
class with an exception filter catches an exception only if the when
clause’s condition is true
.
If an exception filter’s condition is false
, the exception will not be caught and the original exception’s stack-trace information will be preserved until the exception is caught.