How to read optional attributes in XML with default values

When we are reading data from XML data sources, it is very common that when a value is not given for an attribute or an element, we have to use a default value instead. Having to check for the existence of the node each and every time we are reading a value can be annoying and clutter the code. To address this issue I have made a few useful extension method that you can use copy and use in your code. These are written on top of XAttribute class, but you can write similar methods for other types and APIs pretty much the same way.

public static class XmlExtentions
{
    public static string ValueOrDefault(this XAttribute attr)
    {
        return ValueOrDefault(attr, string.Empty);
    }
    public static string ValueOrDefault(this XAttribute attr, string defaultValue)
    {
        return attr == null ? defaultValue : attr.Value;
    }

    public static T ValueOrDefault<T>(this XAttribute attr, T defaultValue) where T : struct
    {
        if (attr == null) { return defaultValue; }
        var value = attr.Value;
        var convertedValue = typeof(T).IsEnum ? Enum.Parse(typeof(T), value) : Convert.ChangeType(value, typeof(T));
        if (convertedValue == null) { return defaultValue; }
        return (T) convertedValue;
    }

    public static T ValueOrDefault<T>(this XAttribute attr, Func<T> defaultDelegate) where T : struct
    {
        if (attr == null) { return defaultDelegate(); }
        var convertedValue = Convert.ChangeType(attr.Value, typeof(T));
        if (convertedValue == null) { return defaultDelegate(); }
        return (T)convertedValue;
    }
}

Once you get it in place. It is pretty easy to use. Assume that we have the following XML document:

<Configuration>
    <Search Enabled="True" RankingAlghorithm="BS77" LowMark="1000" HighMark="2000">
        <Source Name="Orders" Type="WebService" />
        <Source Name="Products" Type="REST" />
    </Search>
<Configuration>

As is shown below, you can read any type of values exactly the same way.

// reading a bool
var isEnabled = sourceNode.Attribute("Enabled").ValueOrDefault(false);

// reading a string
var scopeName = sourceNode.Attribute("Name").ValueOrDefault("Default");

// reading a string and using empty string (string.Empty) as default value
var scopeName = sourceNode.Attribute("Name").ValueOrDefault();

// reading an enum
var sourceType = sourceNode.Attribute("Type").ValueOrDefault(SearchSources.Html);

// reading an integer
var lowMark = sourceNode.Attribute("LowMark").ValueOrDefault(100);

// Using a delegate to provide the default value
var highMark = sourceNode.Attribute("HighMark").ValueOrDefault(()=> App.GetUserSetting("Search.HighMark"));
How to read optional attributes in XML with default values

A simple trick to gain some optimization in your code

I see some times developers do not optimize recursive functions to put less load on stack although many times it can be done with some simple changes in the code without even affecting usability. Lets assume we have a recursive function like the following (which is a C# implementation of the Wikipedia version mentioned here):

public void QuickSort(int[] array, int left, int right) {
  If (left < right) {
    int pivot = Partition(array, left, right);
    QuickSort(array, left, pivot - 1);
    QuickSort(array, pivot + 1, right);
  }
}

To reduce the call stack depth change the if to while and instead of second recursive call to QuickSort change the left index like this:

public void QuickSort(int[] array, int left, int right) {
  while(left < right) {
      int pivot = Partition(array, left, right);
      QuickSort(array, left, pivot - 1);
      left = pivot + 1;
  }
}

Some compilers (e.g. F#) detect and optimize these kind of calls in recursive function (tail recursion), but C# is not one of them. IMHO these kind of optimizations are the responsibility of the developer and compiler needs to focus on many different type of optimizations.
Before I forget and just to be complete, here is the the implementation of Partition function:

private int Partition(int[] array, int left, int right, int pivot){
  int pivotValue = array[pivot];

  // Move pivot to the end of the array
  Swap(array, pivot, right);

  int sortIndex = left;

  for (int i = left; i < right; i++) {
    if (array[i] < pivotValue) {
      Swap(array, i, sortIndex);
      sortIndex++;
    }
  }

  // Move pivot its new place
  Swap(array, sortIndex, right);

  return sortIndex;
}
A simple trick to gain some optimization in your code