UnitsNet
Makes life working with units of measurement just a little bit better.
Install / Use
/learn @angularsen/UnitsNetREADME
Units.NET
Add strongly typed quantities to your code and get merrily on with your life.
No more magic constants found on Stack Overflow, no more second-guessing the unit of parameters and variables.
Changes
ℹ️ The master branch now targets v6, but it is still in pre-release.
New units will be backported to maintenance/v5 until v6 becomes stable.
Upgrading from 5.x to 6.x<br> Upgrading from 4.x to 5.x<br>
Overview
- Overview
- Installing via NuGet
- Static Typing
- Operator Overloads
- Culture and Localization
- Dynamically Parse Quantities and Convert to Units
- Custom units
- Example: Unit converter app
- Example: WPF app using IValueConverter to parse input
- Precision and Accuracy
- Serialize to JSON, XML and more
- Want To Contribute?
- Units.NET on other platforms
- Continuous Integration
- Who are Using This?
- Top Usages by GitHub Repos
Installing via NuGet
Add it via CLI:
dotnet add package UnitsNet
or go to NuGet Gallery | UnitsNet for detailed instructions.
Build Targets
- .NET Standard 2.0
- .NET 8.0 (LTS)
- .NET 9.0 (latest stable)
- .NET 10.0 (preview)
- .NET nanoFramework
Extension Packages
UnitsNet.NumberExtensions.CS14 (C# 14 Extension Members)
For C# 14 projects, use the new extension members syntax (no parentheses):
dotnet add package UnitsNet.NumberExtensions.CS14
using UnitsNet.NumberExtensions.NumberToLength;
// C# 14 extension members syntax, without parantheses
Length distance = 5.Meters; // Instead of Length.FromMeters(5)
Note: Requires '<LangVersion>preview</LangVersion>' and .NET 10 SDK preview for now.
UnitsNet.NumberExtensions (Classic)
For C# 13 and lower (.NET SDK 9 or lower), use the classic extension methods:
dotnet add package UnitsNet.NumberExtensions
using UnitsNet.NumberExtensions.NumberToLength;
// Classic extension methods, with parentheses
Length distance = 5.Meters(); // Instead of Length.FromMeters(5)
Static Typing
// Construct
Length meter = Length.FromMeters(1);
Length twoMeters = new Length(2, LengthUnit.Meter);
// Convert
double cm = meter.Centimeters; // 100
double yards = meter.Yards; // 1.09361
double feet = meter.Feet; // 3.28084
double inches = meter.Inches; // 39.3701
// Pass quantity types instead of values to avoid conversion mistakes and communicate intent
string PrintPersonWeight(Mass weight)
{
// Compile error! Newtons belong to Force, not Mass. A common source of confusion.
double weightNewtons = weight.Newtons;
// Convert to the unit of choice - when you need it
return $"You weigh {weight.Kilograms:F1} kg.";
}
Operator Overloads
// Arithmetic
Length l1 = 2 * Length.FromMeters(1);
Length l2 = Length.FromMeters(1) / 2;
Length l3 = l1 + l2;
// Construct between units
Length distance = Speed.FromKilometersPerHour(80) * TimeSpan.FromMinutes(30);
Acceleration a1 = Speed.FromKilometersPerHour(80) / TimeSpan.FromSeconds(2);
Acceleration a2 = Force.FromNewtons(100) / Mass.FromKilograms(20);
RotationalSpeed r = Angle.FromDegrees(90) / TimeSpan.FromSeconds(2);
Culture and Localization
The culture for abbreviations defaults to Thread.CurrentCulture and falls back to US English if not defined. Thread.CurrentCulture affects number formatting unless a custom culture is specified. The relevant methods are:
- ToString()
- GetAbbreviation()
- Parse/TryParse()
- ParseUnit/TryParseUnit()
var usEnglish = new CultureInfo("en-US");
var russian = new CultureInfo("ru-RU");
var oneKg = Mass.FromKilograms(1);
// ToString() uses CurrentCulture for abbreviation language number formatting. This is consistent with the behavior of the .NET Framework,
// where DateTime.ToString() uses CurrentCulture for the whole string, likely because mixing an english date format with a russian month name might be confusing.
CultureInfo.CurrentCulture = russian;
string kgRu = oneKg.ToString(); // "1 кг"
// ToString() with specific culture and custom string format pattern
string mgUs = oneKg.ToUnit(MassUnit.Milligram).ToString(usEnglish, "unit: {1}, value: {0:F2}"); // "unit: mg, value: 1.00"
string mgRu = oneKg.ToUnit(MassUnit.Milligram).ToString(russian, "unit: {1}, value: {0:F2}"); // "unit: мг, value: 1,00"
// Parse measurement from string
Mass kg = Mass.Parse("1.0 kg", usEnglish);
// Parse unit from string, a unit can have multiple abbreviations
RotationalSpeedUnit rpm1 = RotationalSpeed.ParseUnit("rpm"); // RotationalSpeedUnit.RevolutionPerMinute
RotationalSpeedUnit rpm2 = RotationalSpeed.ParseUnit("r/min"); // RotationalSpeedUnit.RevolutionPerMinute
// Get default abbreviation for a unit, the first if more than one is defined in Length.json for Kilogram unit
string kgAbbreviation = Mass.GetAbbreviation(MassUnit.Kilogram); // "kg"
Gotcha: AmbiguousUnitParseException
Some units of a quantity have the same abbreviation, which means .Parse() is not able to know what unit you wanted.
Unfortunately there is no built-in way to avoid this, either you need to ensure you don't pass in input that cannot be parsed or you need to write your own parser that has more knowledge of preferred units or maybe only a subset of the units.
Example:
Length.Parse("1 pt") throws AmbiguousUnitParseException with message Cannot parse "pt" since it could be either of these: DtpPoint, PrinterPoint.
Dynamically Parse Quantities and Convert to Units
Sometimes you need to work with quantities and units at runtime, such as parsing user input.
There are a handful of classes to help with this:
- Quantity for parsing and constructing quantities as well as looking up units, names and quantity information dynamically
- UnitConverter for converting values to a different unit, with only strings or enum values
- UnitParser for parsing unit abbreviation strings, such as
"cm"toLengthUnit.Centimeter
Quantity - Enumerate quantities and units at runtime
Use Quantity class for looking up QuantityInfo and UnitInfo at runtime.
string[] names = Quantity.Names; // ["Length", "Mass", ...]
QuantityInfo[] qis = Quantity.Infos; // All quantities and their units, types, values.
// Look up quantity by name.
QuantityInfo lengthInfo = Quantity.ByName["Length"];
UnitInfo[] lengthUnits = lengthInfo.UnitInfos;
// Look up unit by enum value (note: for extensibility, will instead look up by name in the future)
UnitInfo cmInfo = Quantity.GetUnitInfo(LengthUnit.Centimeter);
QuantityInfo - Information about a quantity
QuantityInfo makes it easy to get names, units, types and values for a quantity.
This is useful for populating lists of quantities and units for the user to choose.
// Different ways to look up the quantity info.
QuantityInfo lengthInfo = Quantity.ByName["Length"];
lengthInfo = Length.Info;
lengthInfo = Length.FromMeters(1).QuantityInfo;
// The quantity information.
lengthInfo.Name; // "Length"
lengthInfo.UnitInfos; // UnitInfo[] for its units Centimeter, Meter, etc.
lengthInfo.BaseUnitInfo; // UnitInfo for LengthUnit.Meter
lengthInfo.BaseDimensions; // {"Length": 1, "Mass": 0, ...}
lengthInfo.UnitType; // typeof(LengthUnit)
lengthInfo.ValueType; // typeof(Length)
lengthInfo.Zero; // Length.Zero
UnitInfo - Information about a unit
UnitInfo describes a unit, such as its enum value, names and its representation in SI base units.
// Different ways to look up the unit info.
var cm = Quantity.GetUnitInfo(LengthUnit.Centimeter);
if (Quantity.TryGetUnitInfo(LengthUnit.Centimeter, out UnitInfo tryGetCm)) {
cm = tryGetCm;
}
// The unit information.
cm.Value; // Enum value: LengthUnit.Centimeter
cm.Name; // "Centimeter"
cm.PluralName; // "Centimeters"
cm.BaseUnits; // {"Length": Centimeter, "Mass": null, "Time": null, ...}
Construct quantity
All you need is the value and the unit enum value.
IQuantity quantity = Quantity.From(3, LengthUnit.Centimeter); // Length
if (Quantity.TryFrom(3, LengthUnit.Centimeter, out IQuantity quantity2))
{
}
You can also construct from strings, such as mapping between DTO types in an API:
IQuantity quantity = Quantity.From(value: 3, quantityName: "Length", unitName: "Centimeter");
if (Quantity.TryFrom(value: 3, quantityName: "Length", unitName: "Centimeter", out IQuantity? quantity2))
{
}
Or create by just the unit abbreviation, as long as there is exactly one unit with this abbreviation.
// Length with unit LengthUnit.Centimeter
IQuantity quantity = Quantity.FromUnitAbbreviation(3, "
