Skip to content

atmoos/Quantities

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Logo

Quantities

A library to safely handle various types of quantities, typically physical quantities.

master status nuget package License: MIT

Examples

Usage is designed to be intuitive:

  • Instantiation of quantities with static factory methods
    • Quantity.Of(42, Metric<Unit>()): Quantity
  • Conversion to other units with instance conversion methods
    • quantity.To(Imperial<Unit>())

Instantiation

Somewhere in your project, define this global static using directive:

global using static Quantities.Systems;

Then, use quantities intuitively:

Length metres = Length.Of(4, Si<Metre>());
Length miles = Length.Of(12, Imperial<Mile>());
Length kilometres = Length.Of(18, Si<Kilo, Metre>());
Velocity kilometresPerHour = Velocity.Of(4, Si<Kilo, Metre>().Per(Metric<Hour>()));

Conversion

Length miles = metres.To(Imperial<Mile>());
Length kilometres = metres.To(Si<Kilo, Metre>());
Velocity metresPerSecond = kilometresPerHour.To(Si<Metre>().Per(Si<Second>()));
Velocity milesPerHour = kilometresPerHour.To(Imperial<Mile>().Per(Metric<Hour>()));

Operator Overloads

Quantities support common operations such as addition, subtraction, multiplication and division. The operations are "left associative", meaning the units of the left operand are "carried over" to the result when possible.

Time time = Time.Of(3, Metric<Hour>());

Velocity metricVelocity = kilometres / time; // 6 km/h
Velocity imperialVelocity = miles / time; // 4 mi/h

Area metricArea = kilometres * miles; // 347.62 km²
Area imperialArea = miles * kilometres; // 134.22 mi²
Console.WriteLine($"Equal area: {metricArea.Equals(imperialArea)}"); // Equal area: True

Length metricSum = kilometres + miles - metres; // 37.308 km
Length imperialSum = miles + kilometres - metres; // 23.182 mi
Console.WriteLine($"Equal length: {imperialSum.Equals(metricSum)}"); // Equal length: True

Type Safety

As one of the primary goals it to ensure safety when using quantities, type safety is essential.

Additive operations only work on instances of the same type

Power power = Power.Of(36, Si<Watt>());
Mass mass = Mass.Of(0.2, Metric<Tonne>());

// Doesn't compile:
// Cannot implicitly convert type 'double' to 'Power'
Mass foo = mass + power;
Power bar = power + mass;

Multiplication of different quantities is very common, hence compile errors are less frequent. Type safety is always ensured, though.

// Common operation: Ohm's Law
ElectricCurrent ampere = ElectricCurrent.Of(3, Si<Ampere>());
ElectricalResistance ohm = ElectricalResistance.Of(7, Si<Ohm>());

// U = R * I
// The multiplicative result is a different type: ElectricPotential
ElectricPotential potential = ohm * ampere; // 21 V

// Eccentric operation
Time time = Time.Of(5, Metric<Hour>());
Mass mass = Mass.Of(0.2, Metric<Tonne>());

// Doesn't compile
// Operator '*' is ambiguous on operands of type 'Mass' and 'Time'
Mass foo = mass * time;
Time bar = time * mass;
var fooBar = mass * time;

Binary Prefixes

Different types of prefixes are also supported. This is useful for IEC binary prefixes.

Data kibiByte = Data.Of(1, Binary<Kibi, Byte>()); // 1 KiB, binary prefix
Data kiloByte = Data.Of(1.024, Metric<Kilo, Byte>()); // 1 kB, metric prefix
Console.WriteLine($"Equal amount of data: {kiloByte.Equals(kibiByte)}"); // Equal amount of data: True

Should I use this Library?

Yes. The API has stabilised. Furthermore, the library outperforms naive implementations both in terms of performance and accuracy. Additionally, any combination of prefix and unit is supported out of the box for si and metric quantities.

Also, this library supports serialization for json with both System.Text.Json and Newtonsoft.Json. If a specific form of serialization is required, the library provides api's to extend it with custom serialization. (See write and read support.)

Thanks

  • to contributors for providing feedback and ideas.
  • to my sister Lucy Kägi for creating the logo.