Sometimes a picture is worth a thousand words…

I simply ‘cringe’ every time I hear a developer utter the words “I’m going to do this RIGHT!”. Why do we use the words “Right way” and “Wrong way” when describing things? The fact is that there is a lot more than just one “Wrong way” to do something, trust me on this. Further there are a vast multitude of “Right ways” to do anything in software. The simple idea that you know and grasp what is the “Perfect” way of doing something is absurd. Take your pick of a software demi-god and ask them if they ever strove to write something “Right” only to figure out by the end it wasn’t the “Right way”.

So here is a quote of mine that sums it up:

The closer you get to your perfect solution the more your idea of the perfect solution changes and thus the perfect solution cannot be obtained.

We need to recognize that the world of software is not black and white. It is instead an infinite number of shades between the two. The problem we should concern ourselves with is not how to do things “Right”, but rather ask ourselves what is “Good Enough”.

We first recognize the term “Good Enough” to be something that cannot be defined in a concrete way. The term refers to one of those gray areas between black and white and has no consistent definition. As such, for every project, for every class or method, for every line of code we have to redefine “Good Enough”. There are a number of supporting principals of software engineering like YAGNI, SOLID, TDD, etc that aid us to achieve this elusive definition.

For those that want to see a concrete example, this is “Good Enough”:

	public static void Main(string[] args)
	{
		DoSomething(args[0], args[1], int.Parse(args[2]));
	}

… good enough that is for an internal tool that will only ever be called from a single build script. I’ve done this several times on small utilities and I’d argue in those cases there is nothing wrong with it. Yet if you needed to do the same thing for a customer facing utility the same routine might need several classes and a hundred or so lines of code behind it.

In summary, next time you start writing code ask yourself “where on the exponential graph of cost vs. quality do I want to land?”. If I’m writing a routine to keep a heart-implant pumping blood inside someone’s body I’m probably going to want to put some effort into it. However, if I’m writing an argument parser for a command-line app used exclusively by our build then the opposite extreme would apply.

 

How to throw the InnerException of a TargetInvocationException without loosing stack details?

I’ve been plagued by this problem for some time. There are a few common solutions to this:

  1. Option #1 – just leave it alone. The downfall here is that specific types of exceptions cannot be caught easily in calling code. In some instances this can be a very big problem.
  2. Option #2 – re-throwing the InnerExcpetion property. This at least preserves the type of the exception and thus code above you in the call stack will correctly catch and handle exceptions. The problem here is that the stack information previously held in that exception is lost.
  3. Option #3 – Avoiding the problem. If you know the types of the calling parameters you can construct a delegate from the MethodInfo. By calling the delegate (not using DynamicInvoke) the issue is avoided. Again this only works if you have compile-time knowledge of the parameters.

 
Most of the time one of the above has been an acceptable solution; However, recently I ran into the case where none of the above would work. The code has been around a while using option #2 above since the arguments are unknown. Changing the behavior to not throw the original exception type was out since it could break existing client code. The problem that was killing me was the loss of the stack when debugging and monitoring log information. The loss of this information was making spend hours trying to figure out where the thing failed.

So I needed to use MethodInfo.Invoke(), needed the stack and the original excpetion type to be persevered… but how?

Well the first thing I came up with is the following routine which gets down-and-ugly with the Exception class. The catch-block finds the inner-most TargetInvocationException and extracts the InnerException. Then using the Serialization helpers it basically copies the fields of the object to an array. Now we re-throw the exception to set it as the ‘current’ exception when we next call throw without an argument. And finally after we’ve lost our stack we stuff it back in by calling the Serialization helper again to push all the fields back into the exception before calling throw one last time.

Bad Code, do not use

[System.Diagnostics.DebuggerNonUserCode]
[System.Diagnostics.DebuggerStepThrough]
private static void Invoke(MethodInfo method, Object target, params Object[] invokeArgs)
{
	try
	{
		method.Invoke(target, invokeArgs);
	}
	catch (TargetInvocationException te)
	{
		if (te.InnerException == null)
			throw;
		Exception innerException = te.InnerException;

		MemberInfo[] fields = FormatterServices.GetSerializableMembers(innerException.GetType());
		object[] values = FormatterServices.GetObjectData(innerException, fields);

		try { throw innerException; }
		catch(Exception exception)
		{
			FormatterServices.PopulateObjectMembers(exception, fields, values);
			throw;
		}
	}
}

This all worked well… However, I started to wonder about how this might effect some types of exceptions. I started thinking maybe I should serialize & deserialize the object first. I started thinking I was making this too complicated just to preserve a stack trace.

I finally just started reading the exception code and found they have exactly what I want already baked in… just not exposed. The method only preserves the stack, nothing else… perfect. So why not solve a reflection problem with reflection:

[System.Diagnostics.DebuggerNonUserCode]
[System.Diagnostics.DebuggerStepThrough]
private static void Invoke(MethodInfo method, Object target, params Object[] invokeArgs)
{
	try
	{
		method.Invoke(target, invokeArgs);
	}
	catch (TargetInvocationException te)
	{
		if (te.InnerException == null)
			throw;
		Exception innerException = te.InnerException;

		ThreadStart savestack = Delegate.CreateDelegate(typeof(ThreadStart), innerException, "InternalPreserveStackTrace", false, false) as ThreadStart;
		if(savestack != null) savestack();
		throw innerException;// -- now we can re-throw without trashing the stack
	}
}

The person that made this ‘internal’ should be flogged. How very easy of a solution that is and perfectly safe for all types of exceptions. It appears it will even work with remoting, serialization, cross app domains, etc.

My first request for .Net 5.0:

partial class Exception {
	public void PreserveStackTrace();
}

Updated: Apparently this isn’t a new hack, I should have done some google’ing ;)