Marcus writes in his blog how he often ends up with a method that reads an attribute from an XmlNode object. He has optimized his method so that the exception handling will be minimal, since that is pretty expensive.

This is a pretty common scenario for me and I have an even better solution, that does’nt involve exception handling at all.

private static string GetAttribute(XmlNode node, string name)
{
    XmlElement elm = node as XmlElement;
    if (elm == null) {
        return "";
    }
    return elm.GetAttribute(name);
}

This method uses the C# as operator which cast the XmlNode to an XmlElement, if it fails it will return null instead of invoking exception handling.

If you compare the performance of this and Marcus it’s about the same using all three of them when there is an attribute with that name on the XmlNode object, but if it is not then this method is faster. 10.000 iterations of these three different implementations with an attribute that does not exist on the Xml node then we get these results:

  • Marcus first method (try/catch): 0,878 seconds
  • Marcus optimized method (foreach): 0,877 seconds
  • My implementation (cast): 0,001 seconds

Comparisons when hitting a correct attribute looks like this for 1.000.000 iterations:

  • Marcus first method (try/catch): 0,200 - 0,240 seconds
  • Marcus optimized method (foreach): 0,133 - 0,284 seconds
  • My implementation (cast): 0,112 - 0,257 seconds

If you have more attributes on the Xml node then Marcus optimized method will start to suffer. These timings are for 1.000.000 iterations and 6 attributes:

  • Marcus first method (try/catch): 0,323 - 0,342 seconds
  • Marcus optimized method (foreach): 0,523 - 0,533 seconds
  • My implementation (cast): 0,309 - 0,310 seconds

You can also write this code inline (and allocate the XmlElement outside the loop so it’s only allocated once), i.e. don’t create a method for it, and you will have about 10% performance increase on a lot of iterations.

This is what I really like, you may call me an optimization nerd, but that is the beauty of programming…

Anyone have an even better implementation?

Note: The times was measured with QueryPerformanceCounter in Kernel32.dll