Creating custom exceptions is useful for when you need to attach more information to an exception than what is provided by the predefined exception classes or when there is a situation in your application that is not covered by a predefined exception class. This is often the case when you are building custom control or class libraries and you need to generate exceptions that are unique to your components.
Any custom exception class that you build should be derived from the ApplicationException class or at least the Exception class. However, this is not required. In fact, you can throw an exception with any class. This is not recommended, though, because you do lose some of the basic features that the Exception class provides.
When designing a custom exception class, you should keep in mind that the exception information should not be tied to the AppDomain or even the computer. For example, you should not design an exception that is reliant upon a file that resides on a computer. The application that catches the exception may not be running on the same computer and would not have access to the file. All information in the exception class should be able to stand on its own no matter what AppDomain or computer handles the exception.
Creating a simple exception starts with declaring a managed class that derives from the ApplicationException class, as shown in Listing 13.4.
1: public __gc class MyException : public ApplicationException 2: { 3: private: 4: int m_nValue; 5: 6: public: 7: MyException( int nValue, String* sMsg ) : ApplicationException( sMsg ) 8: { 9: m_nValue = nValue; 10: } 11: 12: __property int get_Value() { return( m_nValue ); } 13: };
Your exception class should provide a constructor or multiple constructors, where all allowed values for the exception are passed as parameters. You should not require the user of the exception class to allocate the class, set properties, and then throw the exception. It is cumbersome to use and not a good practice for exception coding.
The MyException class has a constructor that receives nValue and sMsg parameters. The sMsg parameter relates directly to the same parameter in the ApplicationException class and is passed directly into that class. The nValue parameter is part of the custom exception and is saved in a private member.
For any member that you add to your exception class, you should provide a property to retrieve the value. In this case, the get_Value() property is added to return the m_nValue member.
Using custom exceptions is really no different from using one of the predefined exception classes. You still use the throw keyword to generate the exception, except for custom exceptions you simply allocate your exception class instead of a predefined exception. Listing 13.5 shows a simple function that uses the MyException class by throwing and catching the exception.
1: void UseMyException(int nValue) 2: { 3: try 4: { 5: nValue = nValue / 3; 6: 7: if ( nValue < 10 ) 8: throw(new MyException( nValue, "Value less than 10." ) ); 9: 10: if ( nValue > 20 ) 11: throw(new MyException( nValue, "Value greater than 20." ) ); 12: 13: Console::Write( "Value is equal to: " ); 14: Console::WriteLine( nValue ); 15: } 16: catch (MyException* e) 17: { 18: Console::WriteLine( e->get_Message() ); 19: Console::Write( "Value is equal to: " ); 20: Console::WriteLine( e->get_Value() ); 21: } 22: }
As you can see in the listing, throwing and catching the custom exception is identical to using a predefined exception class. The catch determines that the exception is of the MyException class and handles the exception appropriately.
Although this example is simple, you can see how using custom exceptions is easy. You can use the same methods for more complex applications, control libraries, and components, where you need custom exceptions.
Top |