29 October 2012

C# extension - Parse to decimal regardless of regional settings

A problem that often comes up is that decimal numbers are wrongly parsed on different computers due to the regional settings. The following extensions are intended to ensure that a string is correctly parsed to a decimal, regardless of the decimal separator used by the system.

Parse

The first extension returns a string that can be correctly parsed to a decimal type.
/// <summary>
/// Parses a string that is supposed to be a decimal number in
/// such a way that it can be parsed to a decimal data type.
/// </summary>
/// <param name="source">The string to be parsed.</param>
/// <returns>A string that can be parsed to a decimal data type.</returns>
public static string ParseDecimalString(this string source) {
  if (!source.HasValue()) {
    return "0";
  }
  else {
    int indexLastSep = source.LastIndexOfAny(new char[] { '.', ',' });
    StringBuilder result = new StringBuilder();
    for (int i = 0; i < source.Length; i++) {
      if (char.IsDigit(source[i]))
        result.Append(source[i]);
      else if (i == indexLastSep)
        result.Append(CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator);
      else if (i == 0 && source[i] == '-')
        result.Append('-');
    }
    return result.ToString();
  }
}

Cast

The second extension does the casting. I separated this one from the parsing for reusability.
/// <summary>
/// Converts from string to decimal. Returns 0m on failure.
/// </summary>
/// <param name="source">The string.</param>
/// <returns>A decimal representing the string or 0m on failure.</returns>
public static decimal ToDecimal(this string source) {
  decimal result = 0m;
  decimal.TryParse(source.ParseDecimalString(), out result);
  return result;
}

No comments:

Post a Comment