C# создает пользовательский NumberFormatInfo для отображения Free, когда значение валюты равно $0,00

Мне нужно отобразить валюту в моем приложении ASP.NET MVC, но когда валюта равна 0, я бы хотел, чтобы она отображала «Бесплатно» (конечно, локализовано!) Вместо 0,00 долларов США.

Поэтому, когда у меня есть что-то подобное...

Decimal priceFree = 0.00;
Decimal priceNotFree = 100.00;

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

Вывод: "0,00 долл. США" "100,00 долл. США"

Я бы хотел, чтобы это было "Бесплатно" "100 долларов США"

Я предполагаю, что для этого можно использовать метод .ToString(string format, IFormatProvider formatProvider), но я не уверен, как это сделать. Очевидно, я хочу повторно использовать как можно больше NumberFormatInfo и переопределять его только тогда, когда ввод равен 0. В этом случае я могу просто вернуть локализованный ресурс, содержащий мою строку «Free».

Итак, как мне это сделать?

Спасибо


person Justin    schedule 05.10.2010    source источник
comment
Я бы рекомендовал ввести класс Money/Currency вместо передачи десятичных знаков. Это позволит вам сделать это намного проще, и потому, что с валютой происходит гораздо больше, чем с десятичными дробями.   -  person Chris Missal    schedule 05.10.2010


Ответы (4)


Я думаю, что самым простым способом будет метод расширения:

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

Если вы хотите использовать IFormatProvider, есть хороший пример на MSDN.

person driis    schedule 05.10.2010
comment
Я не большой поклонник методов расширения, это моя основная причина. Но в данном случае это может быть плохой отговоркой. Самое простое решение часто является лучшим, и в этом случае метод расширения очень прост. - person Justin; 05.10.2010
comment
Кстати: Если есть возможность, вы можете предоставить дополнительную информацию о значении ‹= 0m. Я не супер семья с синтаксисом 0m. Спасибо! - person Justin; 05.10.2010
comment
Хорошо... так что ‹a href=msdn.microsoft.com/en-us/library/› объясняет m. Мне было любопытно, какое значение ‹= 0m вернет для отрицательного числа. Но я предполагаю, что в этом случае нет такого понятия, как отрицательная цена. - person Justin; 05.10.2010
comment
Несмотря на то, что это представляет собой цену, десятичная дробь может быть отрицательной. Если вместо этого вы использовали пользовательский класс для валюты, вы можете запретить это. - person Chris Missal; 06.10.2010

Использовать

.ToString("$###.00;;Free")
person Viv    schedule 05.10.2010
comment
+1, красиво. Для всех, кто еще не видел этого: [The ; Разделитель разделов ](msdn.microsoft.com/en-us/library/ 0c899ak8.aspx#SectionSeparator). - person Jeff Ogata; 05.10.2010
comment
Кажется интересным. Можете ли вы предоставить ссылку или, возможно, немного подробнее описать свой ответ? Я не совсем уверен, что там происходит со строкой формата. Кажется, это не очень удобно для локализации. - person Justin; 05.10.2010
comment
Спасибо drift за ссылку. Мне нравится эта идея, но если вы не можете сделать ее удобной для локализации, я думаю, что метод расширения — это то, что нужно для этого. - person Justin; 05.10.2010
comment
@Justin: Вы можете локализовать строку формата так же легко, как и бесплатную строку ... (или составить ее из локализованной строки Free). - person Reed Copsey; 05.10.2010
comment
Привет Рид. Я согласен, что мог бы локализовать правила, но для этого нужно знать, как другие культуры локализуют свою валюту. Поскольку это поведение встроено в структуру с использованием .ToString(C), я бы предпочел его. Я поклонник этого конкретного решения, оно аккуратное и здорово иметь в наборе инструментов! - person Justin; 06.10.2010

Как насчет метода расширения:

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

потом

priceFree.FreeString();
priceNotFree.FreeString();
person Robaticus    schedule 05.10.2010

Вместо того, чтобы использовать собственный IFormatProvider и передавать его каждый раз, как насчет этого:

 public static class MyFormatter
    {
        public static string ToFreeString(this decimal d)
        {
            return d == 0 ? "Free" : d.ToString("d");
        }
    }
person Aliostad    schedule 05.10.2010