Created
November 30, 2021 07:16
-
-
Save markusjohnsson/b4b65a9152e048a12238b130ea393aac to your computer and use it in GitHub Desktop.
Units of measure in C#
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
class Unit | |
{ | |
public string Name {get; private set;} | |
protected Unit(string name) | |
{ | |
Name = name; | |
} | |
public static readonly Unit DimensionLess = new Unit(" "); | |
public static readonly Unit Meters = new Unit("meters"); | |
public static readonly Unit Seconds = new Unit("seconds"); | |
public static Unit operator / (Unit a, Unit b) | |
{ | |
if (a.Name == b.Name) return DimensionLess; | |
return new FractionUnit(a, b); | |
} | |
public static Unit operator * (Unit a, Unit b) | |
{ | |
if (a == DimensionLess) return b; | |
if (b == DimensionLess) return a; | |
var aFrac = a as FractionUnit; | |
if (aFrac != null && b == aFrac.Under) | |
return aFrac.Over; | |
var bFrac = b as FractionUnit; | |
if (bFrac != null && a == bFrac.Under) | |
return bFrac.Over; | |
return new MultUnit(a, b); | |
} | |
public static Scalar operator * (double a, Unit b) | |
{ | |
return new Scalar(a, b); | |
} | |
} | |
class MultUnit : Unit | |
{ | |
public Unit A {get; private set;} | |
public Unit B {get; private set;} | |
public MultUnit(Unit a, Unit b): base(a.Name + "*" + b.Name) | |
{ | |
A = a; | |
B = b; | |
} | |
} | |
class FractionUnit : Unit | |
{ | |
public Unit Over {get; private set;} | |
public Unit Under {get; private set;} | |
public FractionUnit(Unit over, Unit under): base(over.Name + "/" + under.Name) | |
{ | |
Over = over; | |
Under = under; | |
} | |
} | |
class Scalar | |
{ | |
public double Value { get;private set;} | |
public Unit Unit {get; private set;} | |
public Scalar(double v, Unit u) | |
{ | |
Value = v; | |
Unit = u; | |
} | |
public static Scalar operator + (Scalar a, Scalar b) | |
{ | |
if (a.Unit != b.Unit) | |
{ | |
throw new InvalidOperationException(string.Format("cannot add scalars with units {0} and {1}", a.Unit.Name, b.Unit.Name)); | |
} | |
return new Scalar(a.Value + b.Value, a.Unit); | |
} | |
public static Scalar operator - (Scalar a, Scalar b) | |
{ | |
if (a.Unit != b.Unit) | |
{ | |
throw new InvalidOperationException(string.Format("cannot subtract scalars with units {0} and {1}", a.Unit.Name, b.Unit.Name)); | |
} | |
return new Scalar(a.Value - b.Value, a.Unit); | |
} | |
public static Scalar operator / (Scalar a, Scalar b) | |
{ | |
return new Scalar(a.Value / b.Value, a.Unit / b.Unit); | |
} | |
public static Scalar operator * (Scalar a, Scalar b) | |
{ | |
return new Scalar(a.Value * b.Value, a.Unit * b.Unit); | |
} | |
public static Scalar operator * (double a, Scalar b) | |
{ | |
return new Scalar(a * b.Value, b.Unit); | |
} | |
public static Scalar operator * (Scalar a, double b) | |
{ | |
return new Scalar(a.Value * b, a.Unit); | |
} | |
public override string ToString() | |
{ | |
return string.Format("{0} {1}", Value, Unit.Name); | |
} | |
} | |
public class Program | |
{ | |
public static void Main() | |
{ | |
var distance = new Scalar(100, Unit.Meters); | |
var time = new Scalar(4, Unit.Seconds); | |
Console.WriteLine(distance / time); | |
Console.WriteLine((9.8 * (Unit.Meters/Unit.Seconds)) * (10 * Unit.Seconds)); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment