-2
\$\begingroup\$

I am storing item's price in database as int. Now, I want to display that data in my a app s it were double. I found 2 ways to do this:

class Item
{
    public int Cost { get; private set; }
    public string CostFormatted { get { return ((double)Cost/100).ToString(); } }
}

and second:

class Item
{
    private int cost;

    public int Cost {
        get { return cost; }

        set {
            cost = value;
            CostFormatted = ((double)cost / 100).ToString();
        }
    }
    public string CostFormatted { get; private set; }
}

which one is better to use?

\$\endgroup\$
2
  • \$\begingroup\$ What kind of app is this? Could you be more specific about that? \$\endgroup\$
    – t3chb0t
    Commented Jun 19, 2018 at 12:34
  • \$\begingroup\$ Welcome to Code Review! This question is incomplete. To help reviewers give you better answers, please add sufficient context to your question. The more you tell us about what your code does and what the purpose of doing that is, the easier it will be for reviewers to help you. Questions should include a description of what the code does \$\endgroup\$ Commented Jun 19, 2018 at 13:03

3 Answers 3

2
\$\begingroup\$

IMPORTANT NOTE: consider this a general answer. The specific UI framework you're using leads to what's the best practice to use. If, for example, this is a WPF application then you just need a plain ValueConverter and no properties in your View Model (again...assuming this is your VM).


First of all casting to double you're introducing errors, the same errors you're trying to avoid storing pennies in an int field. Use decimal instead (and consider to use Money - or whatever else your DBE has - inside the database).

I, personally, find extremely confusing to have a property Cost expressed in pennies. You may change the name to make it explicit (something like CostInPennies) or drop it and convert it to/from decimal when you read/write to/from DB (and the unadjusted value).

What's better between alternatives you've proposed? What's the benefit of the first? It's small and it keeps the logic in the right place. I'd rewrite it to be more concise:

public string DisplayCost => Convert.ToString(Cost / 100.0m);

The second one, however, has a great benefit if your object is observable: updating the DisplayCost property keeps the INotifyPropertyChanged stuff inside the DisplayCost setter leading to much cleaner code. If you don't implement INotifyPropertyChanged (or similar) then I'd go with the first one (and I'd not even bother to store the value somewhere, just recalculate it when required).

In any case I'd introduce a simple helper method to perform this formatting (there are good chances it's reused elsewhere), something like:

static class MoneyFormatter {
    public static string PenniesToString(int pennies)
        => Convert.ToString(pennies / 100.0m);
}

You can then test its logic without any Item's implementation detail. In future you may need to handle something else and it's then better to have everything in one place. Don't forget:

  • Thousands separator: it is probably helpful to quickly scan a column of numbers.
  • Rounding: you don't always need precision to one penny, in some circumstances (for example a dashboard) you MAY even round (for example 10,123$ might be displayed as 10k).
  • Currency symbol: if you display amounts using different currencies then you may need to add it.
  • Negative values: for money it's not uncommon to display negative values with a formatting that it's not the same one used for plain numbers.
\$\endgroup\$
1
\$\begingroup\$

I'm afraid this is a wrong approach (I also don't agree with the other answer's helper). The view/UI should be formatting the output. Most components support formatting for strings.

In your case the property should be just a raw value like

public string CostInPercent => Cost / 100.0; // or any other name that makes sense

that the view now formats whatever it likes. Maybe even by adding % symbol to it.

\$\endgroup\$
5
  • \$\begingroup\$ I agree but it really depends which technology he's using for his UI. Assuming this is his VM and not his business logic (!!!) then it might be a dumb WPF control (dumb otherwise a ValueConverter is more appropriate), some simple WinForms control, a raw PropertyGrid or the view model returned to a very simple HTML page which blindly display some tabular data. Anyway, my upv, if possible this should be an UI task. \$\endgroup\$ Commented Jun 19, 2018 at 12:28
  • \$\begingroup\$ @AdrianoRepetti I am storing item's price in database - I don't think it's OP's view-model. But even if it was then still, I can't think of any ui-component that wouldn't be able to format output the way you like. \$\endgroup\$
    – t3chb0t
    Commented Jun 19, 2018 at 12:30
  • \$\begingroup\$ Because you're lucky and you wiped WinForms from your memory! That /100 makes me think he is storing pennies (1/100) instead of decimal values. If he has pennies then he need a property with whole values and not every WinForms control supports databinding (assuming /100 is calculated in the model). Even controls with the required support (which may be a simple format string) can't often perform more sophisticated things (like dynamic rounding to k$, for example) \$\endgroup\$ Commented Jun 19, 2018 at 12:36
  • \$\begingroup\$ @AdrianoRepetti haha, no I didn't ;-) I spent a lot of time with win-forms and (however most of it with dev-express) but let's not argue... who knows what OP is really doing. This question actually extremely lacks context so I'm wondering why I didn't vote to close it... here is anything possible. Ok, now I did VTC, but I should have done it earlier. \$\endgroup\$
    – t3chb0t
    Commented Jun 19, 2018 at 12:40
  • \$\begingroup\$ you're right, actually I answered without any context...it was really better to ask or close (I'm thinking that if that's for a WPF app then I gave a TERRIBLE suggestion) \$\endgroup\$ Commented Jun 19, 2018 at 12:47
1
\$\begingroup\$

I like the first but I would expose decimal also. In the second if you assign cost directly then the CostFormatted = is missed. N2 for two decimal places.

public class Item
{
    public int Cost { get; private set; }
    public decimal CostDecimal { get { return Cost / 100m; } }
    public string CostFormated { get { return string.Format(CostDecimal.ToString("N2")); } }  
    public Item (int cost)
    {
        Cost = cost;
    }
}

And I would call Cost CostInt.

\$\endgroup\$
2
  • \$\begingroup\$ I agree! I'd even leave there ONLY the property with decimal type. \$\endgroup\$ Commented Jun 19, 2018 at 16:13
  • \$\begingroup\$ @AdrianoRepetti I get leaving the int as integer math is faster. \$\endgroup\$
    – paparazzo
    Commented Jun 19, 2018 at 16:14

Not the answer you're looking for? Browse other questions tagged or ask your own question.