C# creating a custom NumberFormatInfo to display "Free" when a currency value is $0.00
Asked Answered
C

4

4

I need to display a currency in my ASP.NET MVC application but when the currency is 0 I would like it to display "Free" (localized of course!) instead of $0.00.

So when I have something like this...

Decimal priceFree = 0.00;
Decimal priceNotFree = 100.00;

priceFree.ToString("C");
priceNotFree.ToString("C");

The output is "$0.00" "$100.00"

I would like it to be "Free" "$100.00"

I imagine I can use the .ToString(string format, IFormatProvider formatProvider) method to accomplish this but I'm not sure how to go about it. Obvious I want to reuse as much of the NumberFormatInfo as possible and only override it when the input is 0. In that case I can simple return a localized resource that contains my "Free" string.

So how do I do this?

Thanks

Centralize answered 5/10, 2010 at 18:55 Comment(1)
I'd recommend introducing a Money/Currency class instead of passing around decimals. That would allow you to do this much more easily and because Currency has a lot more going on with it than decimals do.Billen
M
4

I think the easiest way to go would be an extension method:

public static string ToPriceString(this decimal value) 
{
    if (value <= 0m) 
        return "Free"; // Your localized resource
    else 
        return value.ToString("C");
}

If you want to go with the IFormatProvider, there is a good example on MSDN.

Menander answered 5/10, 2010 at 19:0 Comment(4)
I'm not a huge fan of extension methods is my primary reason. But in this case it might be a poor excuse. Simplest solution is often the best and in this case the Extension method is very simple.Centralize
BTW: Any chance you can provide more information about value <= 0m. I'm not super family with the 0m syntax. Thanks!Centralize
Ok... so <a href="msdn.microsoft.com/en-us/library/…> explains the m. I was curious what value <= 0m would return for a negative number. But I guess in this case there is no such thing as a negative price.Centralize
Even though it represents a price, a decimal can be negative. If you used a custom class for currency instead, you could disallow that.Billen
C
17

Use

.ToString("$###.00;;Free")
Cyrene answered 5/10, 2010 at 19:5 Comment(5)
+1, nice. For anyone else who hasn't seen this before: [The ";" Section Separator ](msdn.microsoft.com/en-us/library/0c899ak8.aspx#SectionSeparator).Hamel
Seems interesting. Can you provide a reference or perhaps describe your answer a bit more? I'm not exactly sure whats going on there with the format string.It doesn't seem very Localization friendly.Centralize
Thanks to adrift for the reference. I like the idea but unless you can make it localization friendly I think the extension method is the way to go for this one.Centralize
@Justin: You can localize the format string, just as easily as your "free" string... (or compose it from a localized "Free" string).Chesson
Hi Reed. I do agree I could localize the rules but that requires knowledge of how other cultures localize their currency. Since this behavior is built into the framework using .ToString("C") I'd favour it. I am a fan of this particular solution its a neat one and great to have in the toolbelt!Centralize
M
4

I think the easiest way to go would be an extension method:

public static string ToPriceString(this decimal value) 
{
    if (value <= 0m) 
        return "Free"; // Your localized resource
    else 
        return value.ToString("C");
}

If you want to go with the IFormatProvider, there is a good example on MSDN.

Menander answered 5/10, 2010 at 19:0 Comment(4)
I'm not a huge fan of extension methods is my primary reason. But in this case it might be a poor excuse. Simplest solution is often the best and in this case the Extension method is very simple.Centralize
BTW: Any chance you can provide more information about value <= 0m. I'm not super family with the 0m syntax. Thanks!Centralize
Ok... so <a href="msdn.microsoft.com/en-us/library/…> explains the m. I was curious what value <= 0m would return for a negative number. But I guess in this case there is no such thing as a negative price.Centralize
Even though it represents a price, a decimal can be negative. If you used a custom class for currency instead, you could disallow that.Billen
H
2

How about an extension method:

public static string FreeString(this decimal dec)
{
   if(dec == 0M)
   {
      return "Free";
   }
   else
   {
      return dec.ToString("C");
   }
}

Then

priceFree.FreeString();
priceNotFree.FreeString();
Hershelhershell answered 5/10, 2010 at 18:59 Comment(0)
J
0

Instead of using a custom IFormatProvider and passing it each time, how about this:

 public static class MyFormatter
    {
        public static string ToFreeString(this decimal d)
        {
            return d == 0 ? "Free" : d.ToString("d");
        }
    }
Jailbird answered 5/10, 2010 at 19:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.