| Money class a currency convertible money class for the Microsoft .NET Framework by Michael R. Brumm currently in RFC (Request For Comments) stateIntroduction The .NET Framework does not natively contain a data type for storing and converting monetary values. Although the "Decimal" structure provides the precision necessary for performing accounting calculations, it does not store any information regarding the currency it represents, and it does not allow for conversion between currencies. In addition, the .NET Framework contains an incomplete definition of world currencies in the
System.Globalization namespace.In other words, unless you are dealing with a single currency, the .NET Framework lacks the functionality needed to deal with money. In today's global economy, this cause big problems when developing globalized applications. It is my hope that we (the .NET community) can develop a standard way of representing money, and (possibly) have it included in a future core library. To facilitate this, I am posting a proposed implementation and an RFC to the
appropriate .NET communities. Proposed Implementation The implementation contains the following main types:- Money structure
Contains the amount of money and the currency in which the money is represented. - Currency enumeration
An enumeration of all the world's currencies. -
CurrencyInfo class
Provides supporting routines for retrieving information about currencies, currency converters, and the current thread's display currency. - ICurrencyConverter interface
Provides the most basic requirements for a currency converter.
Rationales for Implementation Money as a Structure
- Money was implemented as structure, so it behaves as a value type, which I believe is what most programmers would expect from such a primitive data type.Money.ToString() Formats and Money.Parse()
- By default, the ToString method returns a string which can be parsed back into a value using the Parse method. However, ToString also supports two display formats: "L" (or "l") and "M" (or "m"). These formats are easy for humans to read, but they are not guaranteed to parse. No Arithmetic Operations or Comparisons Defined for Money
- Money cannot be added, subtracted, multiplied, or divided, etc... The reason for this is that when two Moneys are represented by different currencies, a conversion must occur before arithmetic operations can be performed. Without knowing the context of the operation, it is impossible to determine which currencies should be converted, and in which currency the result should be represented. If you wish to perform an arithmetic operation or comparison, first convert all Moneys to the
desired common currency, and then perform the operations on their Amount properties. I realize that this may seem cumbersome, but it ensures that any programmer dealing with the Money class is aware of the conversion, instead of having it invisibly happen in the background. Otherwise, syncronization issues (not pausing updates to the converter's conversion tables, for instance) are just one of many issues which might fester in the obscurity provided by invisible conversions. I predict this
will be the most contentious point of the implementation, and I am open to constructive criticism, so let me know if you disagree with this. Enumerated Currencies
- Because currencies are occasionally established and abandoned, a fixed enumeration might seem inappropriate. However, the alternatives of using (1) numeric constants or (2) text identifiers to define currencies would be either (1) inconvenient or (2) inefficient. Besides, this implementation is backward and forward compatible if new currencies are added or abandoned. Backward and Forward Compatibility
- Although a currency is defined as an Int16 enumeration, this enumeration is not verified or enforced by any method or property. In other words, the enumerations are only designed as a tool to help developers when writing code. Why use an enumeration if it is not enforced? Because it is a lot easier to manage this source code: balance = new Money(Currency.USDollar, 1000); than this: balance = new Money(840, 1000); or this: balance = new Money(CURRENCY_US_DOLLAR, 1000); Because the enumeration is not enforced, new currency codes can be
used even if they are not defined in the enumeration. For example: balance = new Money((Currency)123, 1000); is perfectly valid.There is a minor caveat: CultureInfo will not return information about any currency not defined in the enumeration. This will also affect the ToString("L") and ToString("M") formats, which display the
numeric ISO currency code instead of the ISO currency symbol when there is no information for a currency. But, because these formats are only designed for display and human readability (and not data storage), this should not be a problem. Everything else will function fine. This means that two different applications running on two different machines using two different versions of the Money runtime library will still integrate seamlessly, even if one of them does not have a version with
up-to-date Currency enumerations and CurrencyInfo. CurrencyInfo Uses .NET Framework's Native Culture and Country Mappings
- The .NET Framework already provides this mapping in RegionInfo.ISOCurrencySymbol. If you need a culture's currency, get the RegionInfo for that culture, and pass the ISOCurrencySymbol from the RegionInfo into CurrencyInfo.GetCurrency. If you need a country's currency, get the RegionInfo for that country, and pass the ISOCurrencySymbol from the RegionInfo into CurrencyInfo.GetCurrency. Admittedly, this may be inconvenient, but it prevents the conflicts which might arise from two different mapping systems.
No Default Currency Converter Defined
- Currency conversion rates change constantly. It would be impossible to define a default currency converter which would work well for any reasonable period of time. In addition, different applications require different accuracies. For this reason, currency converters must be defined by the only people who understand what type of currency conversion their applications require: the developers of the applications themselves. This is why currency conversion is only defined as an interface.
Updates UPDATE: 2003/07/25: I've added an application which demonstrates the usefulness of the Money class and how to implement a currency converter (using data from a website). Check the downloads section.
UPDATE: 2003/07/25: I've added a read-only Regions property to the CurrencyInfoData class. This property provides a backward mapping, from currencies to regions. UPDATE: 2003/05/04:
I've changed the namespace from System.Globalization to MichaelBrumm.Globalization. My main reason for using the System namespace were: 1) to point out that these should be native classes, and 2) to shame Microsoft into including something similar (if not the same) in the .NET Framework. Unfortunately, as some pointed out, this could cause namespace conflicts in the future, so I created a new namespace to avoid complications with future versions of the .NET Framework. I am not particularly happy about using my own name as the namespace base, but this seemed to be the most prevalent and sensible proposal.
Downloads I am releasing both the source code and a binary version. It is my hope that this release is bug-free, but the major reason for this RFC release is to allow others to help test and fix problems with the implementation. If you find any bugs, or have questions or comments, please send an e-mail to: me@michaelbrumm.com The following source code and binary executables are FREE to be used for ANY use, including commercial and non-commercial.HOWEVER, PLEASE DO NOT COMPILE AND RELEASE THIS CODE. I will release a binary version after testing is done, so there should be no need for people to create and distribute their own compilations of this source code. That
would actually go against the intentions I had in releasing this RFC. It would be FAR better if people responded to this RFC and we could all agree on this standardized class than to have 20 different incompatible compilations of the same class. Thank you. Money class: Money class and Currency Conversion demonstration:
| |