20

Does anyone know of an already implemented money type for the .NET framework that supports i18n (currencies, formatting, etc)? I have been looking for a well implemented type and can't seem to find one.

Mateo
  • 1,920
  • 2
  • 21
  • 27
  • 1
    Interestingly enough, this question got closed for being a duplicate of a *newer* question. How that works, you've got me. – Mateo Nov 11 '12 at 20:56

3 Answers3

17

Check this article A Money type for the CLR

A convenient, high-performance money structure for the CLR which handles arithmetic operations, currency types, formatting, and careful distribution and rounding without loss.

jfs
  • 16,758
  • 13
  • 62
  • 88
  • Very interesting. This would have helped on a past project of mine. – Jason Jackson Nov 08 '08 at 04:01
  • 14
    It has problems: (1) I've seen many cases where equal Money values don't equate as equal and you have to cast to decimal first. (2) It's very fat: it contains: Int64, Int32, 3 strings, and a UInt16. The author didn't understand the nature of the decimal type. (3) The hash function is rather suboptimal. (4) You can have fractional cents (that's fine) but the ToString() rounds to two decimal places. – dan-gph Jan 04 '12 at 07:40
  • 2
    Re (1), I should have said that I've seen a case where two equal Money values didn't equate as equal (the internal value of one of them was not normalized properly). – dan-gph Jan 05 '12 at 03:36
  • 3
    While I'm cataloguing problems: (5) It has an implicit conversion from double, which is dangerous (decimal doesn't have that). (6) The IConvertible.ToBoolean is inverted (0 converts to true). (7) Unsupported IConvertible conversions throw NotSupportedException rather than InvalidCastException as per the spec. – dan-gph Jan 05 '12 at 05:30
  • 3
    (8) The MoneyDistributer only has 3 unit tests. That makes me nervous because there are a lot of corner cases that are not tested. – dan-gph Jan 05 '12 at 05:42
  • @dan-gph InvalidCastException (not NotSupportedException) is correct. Verified on the msdn docs for IConvertible – ActiveX Nov 03 '22 at 13:17
9

I think you want to use the decimal data type, and use the appropriate overload for ToString().

CultureInfo current  = CultureInfo.CurrentCulture;
decimal myMoney = 99.99m;

//formats as money in current culture, like $99.99
string formattedMoney = myMoney.ToString("C", current); 
Jason Jackson
  • 17,016
  • 8
  • 49
  • 74
2

i would use integer/long, and use a very low denomination like cents (or pence) - then there would be no decimal to work with, and all calculations can be rounded to the nearest cent.

or, take a look at Martin Fowler's book "Patterns of Enterprise Application Architecture". In that book, he talked about how to implement a money class. http://www.amazon.com/Enterprise-Application-Architecture-Addison-Wesley-Signature/dp/0321127420

Chii
  • 14,540
  • 3
  • 37
  • 44
  • 1
    You have it slightly wrong here. It's not a very low denomination, it's the lowest denomination. It's the only bulletproof answer I've ever found--if you have precision beyond reality you're going to get fractions carried after divisions that shouldn't be carried. – Loren Pechtel Nov 08 '08 at 06:38
  • 6
    The cent is not the lowest denomination in American currency, though; otherwise gas stations couldn't sell gas at $2.149/gal, which they do. Likewise, percentages (such as interest) often result in fractional cents, and rounding isn't always appropriate in intermediate steps. – technophile Nov 08 '08 at 18:58
  • @technophile is right. But I still agree with Chii, using integers to store and process currency for most cases is much more reliable and easier to work with than decimals. Especially when you dont have to think about how decimal point is sometimes a comma in europe – userSteve Jun 01 '22 at 10:33