Saturday, February 10, 2007

Mini Pattern: The Throw Method

This post proposes a standard way to throw exceptions from a class and fill the Exception.Data dictionary with the class' context information.

.NET 2.0 introduced a Data dictionary on the Exception class. This dictionary is ideal for holding context information at the place were the Exception is thrown. In order to be able to reuse the logic across all methods of the class and still use the single line syntax "throw new Exception();" a private Throw method is added to the class.

private void Throw(Exception exception)
{
exception.Data.Add("Name", this.Name);
exception.Data.Add("ID", this.ID);
exception.Data.Add("CreationDate", this.CreationDate);
exception.Data.Add("UserName", this.UserName);

throw exception;
}

The Throw method takes the state of the class and stores it in the Data dictionary of the Exception about to be thrown. This data represents (some of) the context in which the exception occurred.

Use the Throw method in other methods of your class whenever throwing an exception is appropriate.

public void MyPublicMethod(string name)
{
if(String.IsNullOrEmpty(name))
{
Throw(new ArgumentNullException("name"));
}

// method impl.
}

Make sure that you write out the extra information contained in the Exception.Data dictionary to the event log (or other log target) when you catch the exception. It should provide you with a little bit of runtime information to help you hunt down any bugs.

4 comments:

Ramon said...

I think that the actual throw should never be done from a support method. But that is just my opinion.

Better wrap it up in a static support method that just returns an exception

throw ExceptionContext.Fill(new Exception());

obiwanjacobi said...

Yes, The "Throw Method" will appear in the call stack trace, so returning the Exception from the "Throw Method" and throwing it "in context" is one solution for that problem.

But the idea is that you add class instance (member) state to the Exception, so when the Exception that is caught higher up the call stack, it contains context data of the source class instance.

Creating a static helper is possible but you should also pass the class instance in question and know how to extract class instance state for several different classes (and you don't have access to protected/private state). That is why it is proposed as a private method of the class in question.

Anonymous said...

Another stab at the problem would be to store a stackframe and crawal the stack once an exception is caught (this only needs to be done at a boundary, before, say logging the exception). this would enable a more generic mechanism to collect state from within whereever this exception was thrown.

obiwanjacobi said...

When an Exception is caught the StackTrace property will contain the StackFrame of the method that threw the Exception (upto 512 frames). But a StackFrame will only give you meta data about the method; not the class instance it was called on. So there is no way to extract class instance data when the Exception is caught.

The main reason to use the Throw Method (or the Exception.Data dictionary in general) is to have this runtime data available when an Exception is caught. Instance data will tell you so much more about the conditions in which the Exception took place.