So you want to add a quantity or unit that is not yet part of Units.NET?
Sometimes we just have to say no, sorry! 😅 We simply want to avoid bloating the library.
A quantity is a good fit to add, if itLength
has kilometer, feet, nanometer etc.).Length x Length = Area
).double
numeric value, integer values are not well supported and may suffer from precision errors.Ratio
).There are extremely many variations of unit A over unit B, such as LengthPerAngle. Generally speaking, we are less inclined to add these unless they are very common and not too domain specific.
We have made some exceptions to all the above "rules" so start a discussion with us if you still think it belongs in the library.
Ok, enough of that. Let's move on! 😃
In order to build and run tests locally you need to have some tools installed.
.NET 6 SDK
to generate and build codeUnits.NET uses CodeGen, a C# command line app that reads JSON files with quantity and unit definitions and generates C# code.
To add a quantity or a unit:
generate-code.bat
file.Easy peasy. Below are the detailed steps.
1. Add or modify JSON file for a quantity class*
or /
operation, then prefer *
in FromBaseToUnit
and /
in FromUnitToBase
. As an example, Length.Centimeter
is defined as "FromBaseToUnit": "{x} * 100"
and "FromUnitToBase": "{x} / 100"
, instead of {x} / 0.001
and {x} * 0.001
.1e3
and 1e-5
notation instead of 1000
and 0.00001
Inch FromUnitToBase: {x} * 2.54e-2
)PrinterPoint FromUnitToBase: ({x} / 72.27) * 2.54e-2
). If the calculation is not available, specify the most precise constant you can. double
numeric type can represent 15-17 significant decimal digitsPrefer the most widely used abbreviation in the domain, but try to adapt to our conventions.
cm²
, m³
) instead of cm^2
, m^3
∆
for delta (not ▲
)·
for products (N·m
instead of Nm
, N*m
or N.m
)/
over ⁻¹
, such as km/h
and J/(mol·K)
h
for hours, min
for minutes and s
for seconds (m
is ambiguous with meters)l
instead of L
for litersgal (U.S.)
vs gal (imp.)
for gallons
(U.S.)
for United States(imp.)
for imperial / British units[ "tsp", "t", "ts", "tspn", "t.", "ts.", "tsp.", "tspn.", "teaspoon" ]
for VolumeUnit.MetricTeaspoon
where tsp
is used by default in ToString()
The base unit dimensions of the quantity, such as "L": 1
for Length
and "L": 2
for Area
(Length*Length
).
The 7 SI base units are:
L
- LengthM
- MassT
- TimeI
- ElectricCurrentΘ
- TemperatureN
- AmountOfSubstanceJ
- LuminousIntensityBaseUnit
- the intermediate unit of a quantity
when converting from one unit to another with FromUnitToBaseFunc
and FromBaseToUnitFunc
conversion functions. It is typically chosen as an SI derived unit (Meter
, Newtonmeter
, Squaremeter
etc). This choice affects the precision of conversions for much bigger/smaller units than BaseUnit
.
Don't confuse this with the quantity's BaseUnit
, which is discussed to be renamed.
If specified, you can create quantities with consistent units for a given unit system:
new Length(1, UnitSystem.SI).ToString() // "1 m" new Length(1, myBritishEngineeringUnitSystem).ToString() // "1 ft"Examples on
BaseUnits
values:
LengthUnit.Inch
has { "L": "Inch" }
(L=1)AreaUnit.SquareCentimeter
has { "L": "Centimeter" }
, because we ignore dimensions (L=2)VolumeUnit.Cubicfeet
has { "L": "Foot" }
, because we ignore dimensions (L=3)ForceUnit.Newton
has { "L": "Meter", "M": "Kilogram", "T": "Second" }
, because N = 1 kg * 1 m / s² = Kilogram * Meter / Second²
and we ignore the dimensionsForceUnit.PoundForce
has { "L": "Foot", "M": "Pound", "T": "Second" }
, because N = 1 lbm * 1 ft / s² = Pound * Foot / Second²
and we ignore the dimensionsMassConcentrationUnit.GramPerDeciliter
has { "L": "Centimeter", "M": "Gram" }
, because Deciliter = 1 cm * 1cm * 1cm = Centimeter³
and we ignore the dimensionsThe only consequence of not specifying BaseUnits
is that you cannot construct these units by passing a UnitSystem
to the quantity constructor as in the example above.
VolumeUnit.ImperialGallon
has no BaseUnits
, because Volume = Length³
and there is no length unit that when multiplied three times would result in imperial gallon.RatioUnit.DecimalFraction
has no BaseUnits
, because dimensionless units are not made up by any SI base units.to generate unit classes, unit enumerations and base class for tests.
3. Reopen solution to load all new filesThis step might no longer be necessary, I think Visual Studio 2017 and the new .csproj format automatically loads new files automatically.
4. Fix generated test stubs to resolve compile errors testsInchesInOneMeter
in LengthTests.cs
39.37007874
from an online unit conversion calculator, it has 10 significant figures so that is plentyInchesInOneMeter
property (see below snippet)Inches In 1 Meter
and it tells me 1 Meter = 39.3701 Inches
(Google typically has fewer significant figures)Example code snippet:
/// <summary>https://link-to-where-i-found-the-value.com</summary> protected override double InchesInOneMeter => 39.37007874;
Make sure all the tests pass. Either run build.bat or run the tests from within Visual Studio with ReSharper or the built-in test runner.
Please see GitHub: Creating a pull request. If you still have any questions, you can reach out in Discussion.
There are many ways to do this, here is one way:
add-somenewunit
For one-offs, this is enough. If you need to create multiple pull requests based on the latest master
branch, or simply keep your fork's branches up to date with the main repo's master
branch, then you need to add the angularsen/UnitsNet repo as a remote to your git clone and fetch it.
# Add main repo as a remote named 'angularsen' git add remote angularsen https://github.com/angularsen/UnitsNet # Fetch branches/tags from all your remotes git fetch # Create and checkout new branch based on latest master git checkout -b add-another-unit angularsen/master # With multiple remotes, you need to tell it what remote a branch should push/pull to, assuming 'origin' is your fork. git branch --set-upstream-to=origin/add-another-unit # Do your work, stage changes, commit and push to your fork. git add -A git commit -m "My commit message" git push # If you need to keep your branch up to date, merge in angularsen's master branch to the current branch you are on. Also push this to your fork. git merge angularsen/master git push # Then visit your fork at https://github.com/your_user/UnitsNet to create a pull request.
Units.NET supports logarithmic units by adding Logarithmic
and LogarithmicScalingFactor
(optional) properties.
LogarithmicScalingFactor
is used to provide a scaling factor in the logarithmic conversion. For example, a scaling factor of 2
is required when implementing the ratio of the squares of two field amplitude quantities such as voltage. In most cases LogarithmicScalingFactor
will be 1
.To create a logarithmic unit, follow the same steps from the previous section making the following adjustments:
Step 1. Add property "Logarithmic": "True"
to the JSON file, just after BaseUnit
. LogarithmicScalingFactor
defaults to 1
if not defined.
Step 4. Provide custom implementations for logarithmic addition and subtraction unit tests. See LevelTests.cs for an example.
Refer to Level.json as an example implementation of logarithmic units.
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4