We can see that some of the individual actions have exception logging, but so does the entire outer block. Deeper actions within may also have the same logging. The end result is a log file littered with redundant rethrown exceptions. We probably only care about logging the deepest occurrence and skipping the rest.

When faced with the same problem recently, I came up with a simple solution. (Keep in mind this only works if your system has a common exception logging abstraction — external code, as always, will do what it will.)

The answer lies in the oft-neglected Data dictionary, present on every exception instance since .NET 2.0. If we stash a piece of information in there indicating the exception has already been logged, we can skip logging on any rethrow.

Here is a reference implementation, using TraceSource as the diagnostic output:

Note the allowance for the Data dictionary to be completely absent or read-only. Since Exception is wide open for extension, there is no telling what you might get when you access such virtual properties.

This doesn’t work for every possible situation; for example, inner exceptions could be rewrapped in new outer exception instances and logged again. Nevertheless, it’s a good start and probably good enough for the 80% case.