Wednesday, March 18, 2009

Using Extension Methods to Verify Assumptions

I was working on something with Tim yesterday, and between us we came up with what I think is a pretty cool trick. We were defining some extension methods on XElement and friends that make it easier to work work XHTML. Something like this:

doc.Html().Div(“foo”).Div(“bar”).Value

Which would pull out the text content of a div with a class of “bar” that was a descendant of a div with a class of “foo”. All well and good, but one of the problems we were trying to address is that we didn’t want to proceed if there was no div of class “foo”. A NullReferenceException would be thrown, but we wanted something more specific. So we came up with this:

public static T OrThrow<T>(this T obj, Exception e) {
    if (obj == null) {
        throw e; 
    } 
    return obj;
}

Which in turn allowed us to write this:

doc.Html().Div(“foo”).OrThrow(new MyException(“no foo”)).Div(“bar”).Value

The clever bit is that the OrThrow extension method is generic on the type it’s invoked on, and it returns that type, so you can insert it into a chained expression and you don’t lose any intellisense. And because of type inference, you don’t actually have to specify the type (you don’t have to type OrThrow<IEnumerable<XElement>>), which cleans up the expression a bit.

This approach is more general than just XHTML, of course. Really, it allows you to insert arbitrary assertions/checks into a series of chained calls using a fairly natural syntax (for some value of “natural”). Nothing you can’t do other ways, but we liked the way this came out enough to want to share it.