Lambdas and anonymous delegates for Debugging
I was posed the problem a few weeks ago that someone has a coding project where the execution engine swallows all exceptions and unless explicitly catching all exceptions (he didn’t want to put a big try catch around everything in production code) there would be little or difficulty in finding if an exception had been thrown in one of his modules.
After some thought, I considered that by utilising anonymous delegates (Action and Func) he would be able to add testing to the existing code very easily, and utilize the Debug/Release modes within Visual Studio.
I proposed, unfortunately with out use of whiteboards or anything which would have been useful, to have within a test harness a helper method which took one of these anonymous delegates, and caught all exceptions and wrote them to Trace to allow him to view them after a test.
public static void ExceptionHelper(Action action)
{
try
{
action();
}
catch (Exception ex)
{
Trace.WriteLine(ex);
}
}
Within the main body of the test harness to add an
#if DEBUG
to allow him to easily swap between running with exceptions handled himself or to allow them to pass through to the execution engine.
public static void TestHarness()
{
Trace.Listeners.Add(new ConsoleTraceListener());
#if DEBUG
ExceptionHelper(FunctionToTest);
#else
FunctionToTest();
#endif
}
Now when Visual Studio runs the test harness in Debug mode, the exceptions will be caught, as the delegate points to the FunctionToTest method which is executed by the action(); line in ExceptionHelper. If the user is in Release mode (i.e. not in Debug) then the Function will be executed as normal.
Comments
Anonymous
February 17, 2010
Don't forgot to add throw; after the Trace.WriteLine call. Also in your example you're not actually using an anonymous delegate. If FunctionToTest took a parameter you could find yourself swimming in overloads of ExceptionHelper. I tend to call these like: ExceptionHelper( () => FunctionToTest() );Anonymous
February 17, 2010
Thanks Josh, I considered doing the call like this but reverted back to this for readability, though I totally agree with you that this would make calling parameterised functions far simpler. Thanks, Dave