Singulink.Globalization.Currency 1.0.0

Prefix Reserved
dotnet add package Singulink.Globalization.Currency --version 1.0.0
                    
NuGet\Install-Package Singulink.Globalization.Currency -Version 1.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Singulink.Globalization.Currency" Version="1.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Singulink.Globalization.Currency" Version="1.0.0" />
                    
Directory.Packages.props
<PackageReference Include="Singulink.Globalization.Currency" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Singulink.Globalization.Currency --version 1.0.0
                    
#r "nuget: Singulink.Globalization.Currency, 1.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Singulink.Globalization.Currency@1.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Singulink.Globalization.Currency&version=1.0.0
                    
Install as a Cake Addin
#tool nuget:?package=Singulink.Globalization.Currency&version=1.0.0
                    
Install as a Cake Tool

Singulink.Globalization.Currency

Chat on Discord Build and Test

Library Package
Singulink.Globalization.Currency View nuget packages
Singulink.Globalization.Currency.Cldr View nuget packages
Singulink.Globalization.Currency.DataProviders View nuget packages

Singulink.Globalization.Currency is a .NET library that provides types like Currency, MonetaryValue and a range of collections and interfaces that make it easy to work with money and currencies in your applications while following best practices. The library is well-documented and follows the same design principles as built-in .NET types and collections. It has been painstakingly tested and optimized to ensure that it is both fast and reliable.

Singulink.Globalization.Currency.Cldr is an optional data package that provides up-to-date currency data from Unicode CLDR instead of the globalization data that ships with the runtime. It includes localized names and symbols for every locale, currencies that are not tied to a region (such as XAU or XDR), historical currencies, and cash rounding rules, and it behaves identically on every runtime and operating system. The data package does not depend on the core library, so it can always be updated to the latest CLDR release without changing the core library version, and its version mirrors the CLDR version.

Singulink.Globalization.Currency.DataProviders contains the ICurrencyDataProvider abstraction that data packages implement. It is referenced by the other two packages and does not normally need to be referenced directly.

Key Features

✔️ Wide range of string formatting options for every scenario (including ISpanFormattable support)
✔️ Four types of money bag collections for working with multiple currencies at once
✔️ Collection expression/literal syntax support
✔️ Builds currency data from built-in system globalization data, or from embedded Unicode CLDR data with the optional CLDR package
✔️ Standard and cash rounding rules for every currency (cash rounding requires the CLDR package)
✔️ Support for custom currency registries, i.e. for cryptocurrency support
✔️ Generic math support (.NET)
✔️ Extensive ReadOnlySpan<char> lookup support (.NET 9+)
✔️ Full AOT and WinRT support
✔️ Extensive test coverage

We are a small team of engineers and designers dedicated to building beautiful, functional, and well-engineered software solutions. We offer very competitive rates as well as fixed-price contracts and welcome inquiries to discuss any custom development / project support needs you may have.

This package is part of our Singulink Libraries collection. Visit https://github.com/Singulink to see our full list of publicly available libraries and other open-source projects.

Installation

The packages are available on NuGet - simply install the Singulink.Globalization.Currency package, and optionally the Singulink.Globalization.Currency.Cldr package for CLDR-based currency data.

Supported Runtimes: Everywhere .NET Standard 2.0 is supported, including:

  • .NET
  • .NET Framework
  • Mono / Xamarin

End-of-life runtime versions that are no longer officially supported are not tested or supported by this library.

Usage

Currencies and monetary values

// Currencies come from the default registry, which is built from system globalization data unless a different registry is registered:
var usd = Currency.GetCurrency("USD");

// Monetary values are immutable and carry their currency:
var price = new MonetaryValue(19.99m, usd);
var total = price * 3;                                // USD 59.97
var withTax = (total * 1.13m).Round();                // USD 67.77 (rounded to the currency's 2 decimal digits)

// Values of different currencies can't be mixed by accident:
var eur = new MonetaryValue(10m, "EUR");
// total + eur                                        // throws ArgumentException

// Formatting and parsing are culture-aware:
withTax.ToString();                                   // "USD 67.77" (current culture)
withTax.ToString("C", CultureInfo.GetCultureInfo("en-US")); // "$67.77"
MonetaryValue.Parse("$67.77", MonetaryStyles.LocalSymbol, CultureInfo.GetCultureInfo("en-US"));

Money bags

Money bags hold amounts in multiple currencies at once and come in mutable, immutable, sorted and unsorted flavors:

var bag = new MoneyBag { new(100m, "USD"), new(50m, "EUR") };
bag.Add(new MonetaryValue(25m, "USD"));               // USD 125, EUR 50
bag.Round();

ImmutableSortedMoneyBag snapshot = [new(1m, "CAD"), new(2m, "USD")];

Rounding and cash rounding

Every currency has a RoundingPolicy describing its decimal digits and any rounding increment. Currencies can also have a CashRoundingPolicy for physical cash transactions, which differs from the standard policy for currencies whose smallest coins have been withdrawn:

CurrencyRegistry.SetDefaultProvider(CldrCurrencyData.Provider); // At application startup, see below

var amount = new MonetaryValue(10.03m, "CAD");
amount.Round();                                       // CAD 10.03
amount.RoundToCash();                                 // CAD 10.05 (Canada withdrew the penny)

new MonetaryValue(10.49m, "SEK").RoundToCash();       // SEK 10 (Sweden rounds cash to whole kronor)

Cash rounding rules are not part of the globalization data that ships with .NET, so RoundToCash() throws NotSupportedException for currencies from the system registry. Install the Singulink.Globalization.Currency.Cldr package to get them, or initialize the CashRoundingPolicy property when creating custom currencies.

Allocation

Splitting an amount into parts without losing or inventing cents is handled by Allocate(). The parts are rounded to the currency's smallest unit and any remainder is distributed so the parts always sum to the original value:

var total = new MonetaryValue(100m, "USD");

total.Allocate(3);              // USD 33.34, USD 33.33, USD 33.33
total.Allocate(50, 30, 20);     // USD 50.00, USD 30.00, USD 20.00 (proportional to the ratios)
total.Allocate(3, new RoundingPolicy(0)); // USD 34, USD 33, USD 33 (whole dollars)

// Cash allocations use the currency's cash rounding policy, so no part needs a coin that does not exist:
new MonetaryValue(100m, "CAD").AllocateToCash(3); // CAD 33.35, CAD 33.35, CAD 33.30

CLDR currency data

The Singulink.Globalization.Currency.Cldr package embeds currency data from the Unicode Common Locale Data Repository (CLDR) and exposes it as a data provider. Register it as the default registry once at application startup, before any currencies or monetary values are used:

CurrencyRegistry.SetDefaultProvider(CldrCurrencyData.Provider);

The default registry then contains currencies that are currently legal tender. Non-tender codes like XAU (gold) and historical currencies can be included as well, or used through separate registries:

CurrencyRegistry.SetDefaultProvider(CldrCurrencyData.Provider, CurrencyTypes.CurrentTender | CurrencyTypes.CurrentNonTender);

var cldr = CurrencyData.Load(CldrCurrencyData.Provider);
var everything = cldr.CreateRegistry(CurrencyTypes.All);
var gold = everything["XAU"];

Any ICurrencyDataProvider implementation can be used in place of the CLDR package, for example to load data that the application downloads at runtime. See the data provider guide for details.

Custom currencies and registries

var bitcoin = new Currency("BTC", "Bitcoin", "₿") {
    RoundingPolicy = new RoundingPolicy(8),
};

var registry = new CurrencyRegistry("Crypto", [bitcoin]);
var value = new MonetaryValue(0.5m, bitcoin);

Further Reading

The project documentation site has guides covering currencies and registries, monetary values, rounding and allocation, formatting, parsing, money bags and data providers, concept articles on currency identity and localization, and the fully documented API.

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net8.0-windows10.0.19041 is compatible.  net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net9.0-windows10.0.19041 is compatible.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed.  net10.0-windows10.0.19041 is compatible. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.0 49 9/29/2026