Click here to Skip to main content
15,867,308 members
Articles / Programming Languages / C#

Money pattern

Rate me:
Please Sign up or sign in to vote.
4.94/5 (14 votes)
4 Nov 2014CPOL5 min read 43.3K   589   22   13
Pattern for representing monetary value in your applications.

Introduction

Money is a blood of Economy. So a large amount of applications handle monetary values - finance and trading applications, every app that allows users to sell or buy something, and even computer games. Probably, most of apps operates with money. But as developers we still don't have special data type for using within monetary value in base class libraries in programming languages that we use and the lack of such type causes some troubles.

In this short article I'm going to explain Money Pattern suggested by Martin Fowler in his book "Patterns of Enterprise Application Architecture" that solves that troubles.  I'm going to cover a few things - what it is, why do we need it and where it is applicable.  I want to get across my idea about using this pattern and suggest my implementation of .NET class library that implements the pattern.

 

Background

The lack of special data type for representing monetary value is not a big deal when your application manipulates only one currency. But if you are working on app that operates multiple currencies it definitely might become the source of headache and some unpleasant mistakes. I suppose you want to avoid the situation when your or your colleagues' code performs any calculation with different currencies without conversion according to exchange rate. And I have faced with this situation in my developer practice more than once. Projects grow, money data come from different sources - databases, XML, SOAP and different currencies, new developers join the team. And here we are - someone adding dollars to euro or comparing 100 dollars with 100 euro without taking into account exchange rate. Slightly worrying situation, isn't it? It is. And I'm totally agree with Martin Fowler who suppose that Money data type should be implemented in all mainstream programming languages by default.

The key idea of Money Pattern is using special reference data type for representing monetary value which contains:

  1. Amount of money
  2. Currency of monetary value
  3. Overloaded comparison operators that do not allow perform comparison without taking into account exchange rate
  4. Overloaded arithmetic operators that do not allow to perform calculations with different currencies without conversion one to another.
  5. Some other helper methods which might be usefull for working with money

Pic. Money Pattern by Martin Fowler

 

So I created class library which contains Money class - my implementation of this pattern for .NET developers. You can use it "as-is" or modify the code on your own.

 

Using the Money class

At first, I'm going to show how to use my implementation of Money pattern. Then I'm going to talk about the implementation. In order to use Money type you should add reference to Sybinfotech.Finance library into your project.

Then, you can create instances of Money class or use it's extension methods for common value types. I' going to demonstrate all the methods that it has and how it works in short pieces of code.

Аt first, let's create a couple of instances of the class in different currencies and try convert one to another using static method ConvertToCurrency(Money sourceValue, Currency destinationCurrency, double exchangeRate):

C#
Money euroMoney = new Money(100.2, Currency.EUR);
Money dollars = Money.ConvertToCurrency(euroMoney, Currency.USD, 1.25);
//output: 125.25
Console.WriteLine("{0} euro = {1} dollars ", euroMoney.Amount, dollars.Amount);

Now, we are going to try what I was talking above - perform some calculations on different currencies:

C#
var sum = euroMoney + dollars; //throws an exception 

This code will throw InvalidCastException as expected cause we are trying to add money in different currencies. You will get the same exception for all arithmetic operations in case of different currencies of operands.

Also you can get instance of Money from value types using extension method ToMoney()

C#
 var sum = 150.ToMoney(Currency.USD) + Money.ConvertToCurrency(15.5.ToMoney(Currency.EUR), Currency.USD, 1.25);

//output: 169.375

Console.WriteLine(sum);

Now that's ok. We convert euro before adding to dollars. And there is one more property which finance apps often need for creating reports - Text. It returns text representation of Money instance taking into account money currency:

C#
Console.WriteLine(125.15.ToMoney(Currency.USD).Text); //one hundred twenty five dollars fifteen cents
Console.WriteLine(125.15.MoneyToText(Currency.USD)); //one hundred twenty five dollars fifteen cents
Console.WriteLine(1205.ToMoney(Currency.RUR).Text); //одна тысяча двести пять руб.

As you can see there is other one extension method for value types - MoneyToText, which allows us to get text representation of money amount without explicit creation of Money instance.

 

The Money class

                                                                       The Money class

My implementation of Money pattern -the  Money class, contains several public properties:

C#
public decimal Amount { get; set; } 

public Currency SelectedCurrency { get; set; } 

public string Text
{
       get
       {
                return AmountToText();    //returns text representation of money amount
       }
}

 

I should notice that every instance of Money has public property of type Currency which specify selected currency for concrete instance of Money type. Currency is just an enum and you can extend it with new currencies:

C#
/// <summary>
/// 3-symb representation of currency
/// </summary>
public enum Currency
{
        RUR, USD, EUR
}
And you should specify Currency when you create new instance of Money. For arithmetic operations on Money instances the class implemets overloaded aritmetic operators:
C#
public static Money operator +(Money firstValue, Money secondValue);

public static Money operator -(Money firstValue, Money secondValue);

public static Money operator *(Money firstValue, Money secondValue);

public static Money operator /(Money firstValue, Money secondValue);

These operators do not allow to performs any calculations between different currencies without conversion according to exchange rate. If you want to calculate different currencies you must use static ConvertToCurrency method for one of operands:

C#
public static Money ConvertToCurrency(Money sourceValue, Currency destinationCurrency, double exchangeRate);

For performing correct comparison between currencies the Money class overrides Equals method:

C#
public override bool Equals(object obj)
{
    if (obj == null) return false;

    Money money = obj as Money;
    return (this.Amount == money.Amount && this.SelectedCurrency == money.SelectedCurrency);
}

public bool Equals(Money money)
{
    if ((object)money == null) return false;

    return (this.Amount == money.Amount && this.SelectedCurrency == money.SelectedCurrency);
}
And overloaded == operator returns true only if both Money instances have the same value for Amount property and SelectedCurrency. There are all comparison operators overloaded in the class.
 
In case if you want to implement text representation for new currency you should modify AmountToText()  method and implement methods that return text representation by analogy:
private string AmountToText()
{
     string sumText = "";
     switch (this.SelectedCurrency)
     {
                case Currency.RUR:
                    if (this.IntegralPart != 0)
                        sumText += GetAmountTextRUR(this.IntegralPart) + " руб. ";
                    if (this.FractionalPart != 0)
                        sumText += GetAmountFractionalTextRUR(this.FractionalPart) + " коп.";
                    break;
                case Currency.USD:
                    if (this.IntegralPart != 0)
                        sumText += GetAmountTextEN(this.IntegralPart) + " dollars ";
                    if (this.FractionalPart != 0)
                    {
                        sumText += GetAmountFractionalTextEN(this.FractionalPart);
                        sumText += " ";
                        sumText += this.FractionalPart == 1 ? "cent" : "cents";
                    }
                    break;
                case Currency.EUR:
                    if (this.IntegralPart != 0)
                        sumText += GetAmountTextEN(this.IntegralPart) + " euro ";
                    if (this.FractionalPart != 0)
                    {
                        sumText += GetAmountFractionalTextEN(this.FractionalPart);
                        sumText += " ";
                        sumText += this.FractionalPart == 1 ? "cent" : "cents";
                    }
                    break;

                default: throw new NotImplementedException("There is no text representation converter for this currency!");
            }
            return sumText.Trim();
}

Sybinfotech.Finance library also has another class - MoneyExtenshions which contains extension methods for getting Money instances and text representations from .NET value data types - decimalintdouble.

public static Money ToMoney(this decimal amount, Currency currency)

public static Money ToMoney(this double amount, Currency currency)
...

public static string MoneyToText(this double amount, Currency currency)

public static string MoneyToText(this decimal amount, Currency currency)

...

Full source code of library with comments is attached.

Summary

In this article I've tried to explain Money pattern and suggest my own implementation of this pattern for .NET developers.

I hope that you found this article useful and please feel free to use or modificate the  attached library that implements Money pattern.

Thanks!

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer
Russian Federation Russian Federation
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionIs this Value object design pattern ? Pin
Shivprasad koirala16-Aug-16 1:04
Shivprasad koirala16-Aug-16 1:04 
This seems like a subset of Value object design pattern of DDD Value Object Design Pattern in C#[^]

It would be a bad idea to create a money data type as there are huge variations on how money behaves geographically.

Questionthanks you ! Pin
Member 1068004217-Mar-15 6:03
Member 1068004217-Mar-15 6:03 
Suggestionyou can't multiply money with money Pin
sx20086-Nov-14 10:44
sx20086-Nov-14 10:44 
QuestionPotential Enhancement Pin
BlackburnKL6-Nov-14 5:01
BlackburnKL6-Nov-14 5:01 
QuestionRe: Potential Enhancement Pin
s2bert10-Nov-14 5:39
s2bert10-Nov-14 5:39 
QuestionGreat article Pin
Tomaz Koritnik5-Nov-14 2:33
Tomaz Koritnik5-Nov-14 2:33 
QuestionLook here for a detailed implementation Pin
Norbert Haberl5-Nov-14 2:05
Norbert Haberl5-Nov-14 2:05 
AnswerRe: Look here for a detailed implementation Pin
Dennis Shchuka5-Nov-14 2:29
Dennis Shchuka5-Nov-14 2:29 
Questionhave you consider to post this as a tip? Pin
Nelek4-Nov-14 22:18
protectorNelek4-Nov-14 22:18 
QuestionInternationalisation issues Pin
NeverJustHere4-Nov-14 21:25
NeverJustHere4-Nov-14 21:25 
AnswerRe: Internationalisation issues Pin
Dennis Shchuka4-Nov-14 22:08
Dennis Shchuka4-Nov-14 22:08 
GeneralRe: Internationalisation issues Pin
ArchAngel1235-Nov-14 8:49
ArchAngel1235-Nov-14 8:49 
GeneralMy vote of 5 Pin
Humayun Kabir Mamun4-Nov-14 16:58
Humayun Kabir Mamun4-Nov-14 16:58 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.