Creating and Throwing Exceptions (C# Programming Guide)
Exceptions are used to indicate that an error has occurred while running the program. Exception objects that describe an error are created and then thrown with the throw keyword. The runtime then searches for the most compatible exception handler.
Programmers should throw exceptions when:
The method cannot complete its defined functionality. For example, if a parameter to a method has an invalid value:
static void CopyObject(SampleClass original) { if (original == null) { throw new System.ArgumentException("Parameter cannot be null", "original"); } }
An inappropriate call to an object is made, based on the object state. For example, trying to write to a read-only file. In cases where an object state does not allow an operation, throw an instance of InvalidOperationException or an object based on a derivation of this class. This is an example of a method that throws an InvalidOperationException object:
class ProgramLog { System.IO.FileStream logFile = null; void OpenLog(System.IO.FileInfo fileName, System.IO.FileMode mode) {} void WriteLog() { if (!this.logFile.CanWrite) { throw new System.InvalidOperationException("Logfile cannot be read-only"); } // Else write data to the log and return. } }
When an argument to a method causes an exception. In this case, the original exception should be caught and an ArgumentException instance should be created. The original exception should be passed to the constructor of the ArgumentException as the InnerException parameter:
static int GetValueFromArray(int[] array, int index) { try { return array[index]; } catch (System.IndexOutOfRangeException ex) { System.ArgumentException argEx = new System.ArgumentException("Index is out of range", "index", ex); throw argEx; } }
Exceptions contain a property called StackTrace — this string contains the name of the methods on the current call stack, along with the file name and line number where the exception was thrown for each method. A StackTrace object is created automatically by the CLR from the point of the throw statement, so exceptions must be thrown from the point where the stack trace should begin.
All exceptions contain a property called Message — this string should be set to explain the reason for the exception. Note that security sensitive information should not be put in the message text. In addition to Message, ArgumentException contains a property called ParamName that should be set to the name of the argument that caused the exception to be thrown. In the case of a property setter, ParamName should be set to value
.
Public and protected methods should throw exceptions whenever they cannot complete their intended function. The exception class thrown should be the most specific exception available that fits the error conditions. These exceptions should be documented as part of the class functionality, and derived classes or updates to the original class should retain the same behavior for backwards compatibility.
Exceptions should not be used to alter the flow of a program as part of normal execution--they should only be used to report and handle error conditions. Exceptions should not be returned as a return value or parameter instead of being thrown. Programmers should not throw System.Exception, System.SystemException, NullReferenceException or IndexOutOfRangeException intentionally.
Defining Exception Classes
Programs can throw any of the predefined exception classes in the System namespace (except where previously noted), or create their own exception classes by deriving from ApplicationException. The derived classes should define at least four constructors — one default constructor, one that sets the message property, and one that sets both the Message and InnerException properties. The fourth constructor is used to serialize the exception — new exception classes should be serializable. For example:
public class InvalidDepartmentException : System.ApplicationException
{
public InvalidDepartmentException() {}
public InvalidDepartmentException(string message) {}
public InvalidDepartmentException(string message, System.Exception inner) {}
// Constructor needed for serialization
// when exception propagates from a remoting server to the client.
protected InvalidDepartmentException(System.Runtime.Serialization.SerializationInfo info,
System.Runtime.Serialization.StreamingContext context) {}
}
New properties should only be added to the exception class when the data they provide is useful to resolving the exception. If new properties are added to the derived exception class, ToString()
should be overridden to return the added information.
C# Language Specification
For more information, see the following sections in the C# Language Specification:
8.9.5 The throw Statement
8.10 The try Statement
16 Exceptions
See Also
Reference
Exceptions and Exception Handling (C# Programming Guide)
Exception Handling (C# Programming Guide)