Best Practices for Throwing Exceptions from Components
When an application calls a method of your component, the method can provide error information by throwing an exception. The client application can implement an exception handler to trap errors that may be thrown by the method.
There are a number of programming tradeoffs to consider when you select an error generation strategy for your component, but the most important consideration should be the convenience of the developer who will use your component. If it is possible for your component to handle an exception internally, it should. The client application should receive exceptions from your component only when additional intervention is required.
When you raise exceptions, the developer who calls your method has the choice of handling the exception or allowing it to be thrown further up the call stack.
Whatever exceptions you throw from your component should be logically consistent. If you decide to create custom exceptions to report errors unique to your component, they should be limited to reporting that particular error. Do not use a general exception when a more specific one can be used. The purpose of raising an exception is to provide the client application with as much information about how to correct the error and keep the program running smoothly as possible.
If you create and throw custom exceptions in your component, they should be well documented so that developers using your component will best be able to handle them. Your documentation should include a description of the exception, the conditions under which it is likely to occur, suggested ways for resolving the error condition, and any error codes or additional information that the exception returns.
Exceptions Are For Exceptional Circumstances
Do not throw exceptions as a means of communicating between components-use events for that. Exceptions should not be thrown in cases where completely expected results occur. For example, a component that reads text files should not throw an exception when it reaches the end of the file. This is a case where an event would be appropriate. By limiting throwing exceptions to exceptional cases, you will help developers to debug their application rapidly by not having to wade through numerous 'expected' exceptions.
COM-Visible Components and Exceptions
If your component is to be called by a COM client, there are additional considerations to be taken into account. All exceptions thrown from a component to a COM client must provide an error code. With standard exceptions, this code is provided "behind the scenes" via the HResult property. If you are creating and throwing custom exceptions, you must set an appropriate HResult value. If your custom exception returns an error condition that is similar to a standard error condition, then the HResult value for that error condition may be used. Otherwise, you can set the value however you choose. In this case, it is important to document all error codes that might be passed via HResult so the developer using your component can implement appropriate responses. For details, see HRESULTs and Exceptions.
Unstructured Error Handling (Visual Basic Only)
Visual Basic .NET also supports unstructured error handling using the On Error Goto syntax. While this kind of error handling will continue to function in your components, it is not recommended that it be implemented. Code written using this method of error handling is difficult to debug and maintain, and it can degrade application performance. Structured error handling, using the Try...Catch...Finally block, results in code that is easier to maintain, more robust, and more flexible in the way that errors can be handled.