'Convert currency string to decimal?

Objective

Sort a string that is displaying currency data like this $1,995.94 numerically in a set of data.

Code

I'm currently using the below code sample to convert the string value to decimal so that I can sort it properly.

if (sortBy == "checkAmount")
{
    StringBuilder sb = new StringBuilder();
    foreach (var c in Convert.ToString(p.GetType().GetProperty(sortBy).GetValue(p, null)))
    {
        if (!char.IsDigit(c) && c != '.') { continue; }
        sb.Append(c);
    }
    return Convert.ToDecimal(sb.ToString());
}
else
{
    return p.GetType().GetProperty(sortBy).GetValue(p, null);
}

Problem

What's a better way of doing this? It works, and that's cool, but it's not very elegant.

Final Solution

The answer provided by Servy works as expected, and I used that implementation for a while, but a colleague and I found an even better way so I'm documenting it here. BTW, I ended up using this solution in the end.

decimal.Parse(input, NumberStyles.AllowCurrencySymbol | NumberStyles.Number);


Solution 1:[1]

How about this, but only works for one string value. So you need to get your string split by $ and then do the conversion while saving into the array or list

 using System.Globalization;
    //rest of your code

          string str = "$50,550.20";
          decimal decval;
          bool convt = decimal.TryParse(str, NumberStyles.Currency,
            CultureInfo.CurrentCulture.NumberFormat, out decval);
          if (convt) 
          Console.WriteLine(decval);
          Console.ReadLine();

Solution 2:[2]

Here is a simpler solution:

    public static decimal ToDecimal(this string str)
    {
        return decimal.Parse(str, NumberStyles.Currency);
    }

and the unit test:

    [Test]
    public void ToDecimal_Convert_String_To_Decimal()
    {
        Assert.AreEqual(1234M, "1234".ToDecimal());
        Assert.AreEqual(-1234.56M, "$(1,234.56)".ToDecimal());
        Assert.AreEqual(1234.56M, "$1,234.56".ToDecimal());
    }

Solution 3:[3]

decimal amount = decimal.Parse("$123,456.78",
NumberStyles.AllowCurrencySymbol |
NumberStyles.AllowThousands |
NumberStyles.AllowDecimalPoint);

Solution 4:[4]

works for all culture:

var d = decimal.Parse("$497.7", NumberStyles.Currency, CultureInfo.CreateSpecificCulture("us-US").NumberFormat);    

Console.WriteLine(d);

Solution 5:[5]

public static decimal ToDecimalFromStringDecimalOrMoneyFormattedDecimal(this string s)
{
    try
    {
        return decimal.Parse(s);
    }
    catch
    {
        var numberWithoutMoneyFormatting = Regex.Replace(s, @"[^\d.-]", "");
        return decimal.Parse(numberWithoutMoneyFormatting);
    }
}

[Test]
public void Test_ToDecimalFromStringDecimalOrMoneyFormattedDecimal()
{
    Assert.That("$ 500".ToDecimalFromStringDecimalOrMoneyFormattedDecimal() == (decimal)500);
    Assert.That("R -500".ToDecimalFromStringDecimalOrMoneyFormattedDecimal() == (decimal)-500);
    Assert.That("-$ 500".ToDecimalFromStringDecimalOrMoneyFormattedDecimal() == (decimal)-500);
    Assert.That("P 500.90".ToDecimalFromStringDecimalOrMoneyFormattedDecimal() == (decimal)500.9);
    Assert.That("$ -50 0,090,08.08".ToDecimalFromStringDecimalOrMoneyFormattedDecimal() == (decimal)-50009008.08);
}

Solution 6:[6]

We can try to use decimal.TryParse to cast the currency string value to a decimal number.

  • NumberStyles?use NumberStyles.Currency which indicates that all styles except AllowExponent and AllowHexSpecifier are used. This is a composite number style.
  • CultureInfo? we need to set the right culture of currency which align with your currency value.

For this example, $20,000.00 is USA currency we can try to use English (USA) for that, on the other hand 20,000.00€ is euro currency we can try to use English (Ireland) that uses the euro currency.

decimal.TryParse("20,000.00€", NumberStyles.Currency ,CultureInfo.CreateSpecificCulture("en-IE"), out var euro);
Console.WriteLine(euro);
decimal.TryParse("$20,000.00", NumberStyles.Currency ,CultureInfo.CreateSpecificCulture("en-us"), out var dollar);
Console.WriteLine(dollar);

c# online

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 bonCodigo
Solution 2 Red
Solution 3 bilal
Solution 4 robert
Solution 5 Richard
Solution 6 D-Shih