16.7 Implement a Custom Exception Class


Problem

You need to create a custom exception class so that you can use the runtime's exception-handling mechanism to handle application-specific exceptions.

Solution

Create a serializable class that extends the System.ApplicationException class and implements constructors with these signatures.

 public CustomException() : base() {} public CustomException(string message): base(message) {} public CustomException(string message, Exception inner)      : base(message, inner) {} 

Add support for any custom data members required by the exception, including constructors and properties required to manipulate the data members .

Discussion

Exception classes are unique in the fact that you do not declare new classes solely to implement new or extended functionality. The runtime's exception- handling mechanismexposed by the C# statements try , catch , and finally works based on the type of exception thrown, not the functional or data members implemented by the thrown exception.

If you need to throw an exception, you should use an existing exception class from the .NET Framework class library, if a suitable one exists. For example, some useful exceptions include

  • System.ArgumentNullException , when code passes a null argument value to your method that doesn't support null arguments.

  • System.ArgumentOutOfRangeException , when code passes an inappropriately large or small argument value to your method.

  • System.FormatException , when code attempts to pass your method a String argument containing incorrectly formatted data.

If there's no suitable exception class to meet your needs, or you feel your application would benefit from using application-specific exceptions, it's a simple matter to create your own exception class. In order to integrate your custom exception with the runtime's exception-handling mechanism and remain consistent with the pattern implemented by .NET Frameworkdefined exception classes, you should

  • Give your exception class a meaningful name ending in the word Exception , for example, TypeMismatchException or RecordNotFoundException .

  • Extend the ApplicationException class. Your custom exception must ultimately extend the System.Exception class, or the compiler will raise an error when you try to throw the exception; ApplicationException extends Exception and is the recommended base for all application-specific exception classes.

  • Mark your exception class as sealed if you do not intend other exception classes to extend it.

  • Implement additional data members and properties to support custom information that the exception class should provide.

  • Implement three public constructors with the signatures shown here and ensure they call the base class constructor.

     public CustomException() : base() {} public CustomException(string message): base(message) {} public CustomException(string message, Exception inner)      : base(message, inner) {} 
  • Make your exception class serializable so that the runtime can marshal instances of your exception across application domain and machine boundaries. Applying the attribute System.SerializableAttribute is sufficient for exception classes that don't implement custom data members. However, because Exception implements the interface System.Runtime.Serialization.ISerializable , if your exception declares custom data members, you must override the ISerializable.GetObjectData method of the Exception class as well as implement a deserialization constructor with this signature. If your exception class is sealed , mark the deserialization constructor as private; otherwise mark it protected .

     private CustomException(SerializationInfo info,      StreamingContext context) {} 

The GetObjectData method and deserialization constructor must call the equivalent base class method to allow the base class to serialize and deserialize its data correctly. (See recipe 16.1 for details on making classes serializable.)

The CustomException class shown here is a custom exception that extends ApplicationException and declares two custom data members: a string named stringInfo and a bool named booleanInfo .

 using System; using System.Runtime.Serialization; // Mark CustomException as Serializable.  [Serializable] public sealed class CustomException : ApplicationException {     // Custom data members for CustomException.     private string stringInfo;     private bool booleanInfo;     // Three standard constructors and simply call the base class     // constructor (System.ApplicationException).     public CustomException() : base() {}     public CustomException(string message): base(message) {}     public CustomException(string message, Exception inner)          : base(message, inner) {}     // The deserialization constructor required by the ISerialization      // interface. Because CustomException is sealed, this constructor      // is private. If CustomException were not sealed, this constructor      // should be declared as protected so that derived classes can call     // it during deserialization.     private CustomException(SerializationInfo info,          StreamingContext context) : base (info, context) {         // Deserialize each custom data member.         stringInfo = info.GetString("StringInfo");         booleanInfo = info.GetBoolean("BooleanInfo");     }     // Additional constructors to allow code to set the custom data     // members.     public CustomException(string message, string stringInfo,          bool booleanInfo): this(message) {              this.stringInfo = stringInfo;         this.booleanInfo = booleanInfo;     }     public CustomException(string message, Exception inner,          string stringInfo, bool booleanInfo) : this(message, inner) {         this.stringInfo = stringInfo;         this.booleanInfo = booleanInfo;     }     // Read only properties that provide access to the custom data members.     public string StringInfo {         get { return stringInfo; }     }     public bool BooleanInfo {         get { return booleanInfo; }     }     // The GetObjectData method (declared in the ISerializable interface)     // is used during serialization of CustomException. Because      // CustomException declares custom data members, it must override the      // base class implementation of GetObjectData.     public override void GetObjectData(SerializationInfo info,          StreamingContext context) {         // Serialize the custom data members         info.AddValue("StringInfo", stringInfo);         info.AddValue("BooleanInfo", booleanInfo);         // Call the base class to serialize its members         base.GetObjectData(info, context);     }     // Override the base class Message property to include the custom data      // members.     public override string Message {         get {             string message = base.Message;             if (stringInfo != null) {                 message += Environment.NewLine +                      stringInfo + " = " + booleanInfo;             }             return message;         }     }     } 

In large applications, you will usually implement quite a few custom exception classes. It pays to put significant thought into how you organize your custom exceptions and how code will use them. Generally, avoid creating new exception classes unless code will make specific efforts to catch that exception; use data members to achieve informational granularity, not additional exception classes. In addition, avoid deep class hierarchies when possible in favor of broad, shallow hierarchies.




C# Programmer[ap]s Cookbook
C# Programmer[ap]s Cookbook
ISBN: 735619301
EAN: N/A
Year: 2006
Pages: 266

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net