Before I began to code my DICT client, I needed to figure out how to treat error codes defined in RFC 2229 (the DICT protocol). In C++ it was common to return numeric result/status/error codes, but in .NET it’s done differently.
Architectural “prescriptive guidance” encourages the following (see Do You Use Error Codes?) :
Generally, you should avoid using method return codes to indicate error conditions. Instead, you should use structured exception handling. Using exceptions is much more expressive, results in more robust code, and is less prone to abuse than error codes as return values.
The common language runtime (CLR) internally uses exceptions even in the unmanaged portions of the engine. However, the performance overhead associated with exceptions should be factored into your decision. You can return a simple bool value to inform the caller of the result of the function call.
The last statement means: if you can foresee an error condition, you might want to consider a simple boolean return code to avoid the overhead of exceptions.
The dictionary client had quite a few error conditions to deal with—from unsupported commands to the dictionary server administrative shutdown. I decided that exceptions would be much cleaner.
Next step is to take a side in the religious battle of which exception class to derive from. Traditionally, you were advised to derive a custom exception class from ApplicationException:
ApplicationException is thrown by a user program, not by the common language runtime. If you are designing an application that needs to create its own exceptions, derive from the ApplicationException class. ApplicationException extends Exception, but does not add new functionality. This exception is provided as means to differentiate between exceptions defined by applications versus exceptions defined by the system.
Indeed, crank up Reflector, and you’ll see there’s nothing different in ApplicationException from its base, Exception.
And then I found a post on Brad Abram’s blog on this subject which has a comment by Jeffrey Richter saying you should not derive from ApplicationException because it’s useless. Psssttt… Jeffrey Richter has spoken: it’s golden. :) End of controversy.
public sealed class DictionaryServerException : Exception {
…
}
Run this through FxCop and you’ll get a friendly reminder that Exception implements the ISerializable interface and you should too:
Add [Serializable] to type ’DictionaryServerException’.
[Serializable]
public sealed class DictionaryServerException : Exception {
…
}
There. It’s not enough to simply add this attribute. FxCop gives a hint:
If a type is assignable to ISerializable, it should implement GetObjectData. For unsealed types, the GetObjectData method should be callable and overridable by derived types.
This, along with a constructor, which participates in serialization, completes the design of our custom exception class.
One more twist: take a look at the declaration of GetObjectData. If you omit security permission attributes, FxCop reminds you to add them.
Now we’re done. Solid done! Finished code is here: DictionaryServerException.cs.