In my "day job" I've recently been writing a whole bunch of utility classes and macros to bring some conformity to the way errors are detected, handled and propagated within our (unmanaged C++) codebase. This got me to wondering how one might best achieve this in .NET.

Firstly, the standardisation on exceptions as the signalling mechanism helps no end. A large chunk of the unmanaged work I've been doing was related to a generic way to map between the different types and conventions being used for return codes (esp. Win32 BOOL + SetLastError and COM HRESULTs). The most direct analogue to my unmanaged C++ macros would be to catch, process and rethrow exceptions in each function. However, I think everyone would agree that this is bad on at least two levels: from a philosophical viewpoint it is not particularly in keeping with the intended usage of exceptions; and practically the absence of a pre-processor in C# and VB.NET (see Note 1) would make this extremely tedious. The first "sensible" approach I came up with was to sub-class ApplicationException to add any commonly used functionality (logging, for example), then use that as the base class for all of our application exceptions. This is analogous to the common practice of creating an alternative base page class in ASP.NET. This left me with a nagging doubt as regards "system" exceptions (i.e. those not derived from ApplicationException). There seemed to be three possible approaches here:

  1. Use an "application" exception class corresponding to the system exception e.g. MyAppNullReferenceException
  2. Use a more general "application" exception with its InnerException property set accordingly, e.g. MyAppValidationException with an inner exception of NullReferenceException
  3. Use system exceptions, but create them from a "factory" which does the common tasks such as logging

The first option does not seem particularly appealing, not least as there would be no way for other code to make the connection between the application exception and its system counterpart. The second is probably my favoured approach, as it is at least possible to determine the corresponding system exception, whilst still remaining consistent with the suggested handling of "real" application errors. However, the third option also has merit, though I would expect to create both application and system exceptions from any such factory for the sake of consistency.

Now its feedback time. What have other people done in this area? Does the MS exception management application block help at all? What about the enterprise instrumentation framework? Your comments are, as ever, much appreciated.

Notes:

  1. Has anyone else ever considered writing files with, say, a .csx extension that are preprocessed to give valid C# code? See also Note 2.
  2. Has anyone else noticed that a C++ compiler appearing on machines without VS.NET? For example, in "C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\bin" I have what seem to be C++ compiler and linker binaries. I'm not quite sure what installs it, though (.NET SDK, CLR profiler, etc.).