Skip to content

Instantly share code, notes, and snippets.

@WhiteBlackGoose
Last active December 20, 2021 16:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save WhiteBlackGoose/f24353b4d8b0a27860acfbd73056e020 to your computer and use it in GitHub Desktop.
Save WhiteBlackGoose/f24353b4d8b0a27860acfbd73056e020 to your computer and use it in GitHub Desktop.
Advanced measurement units
using System;
var distance = Meter.From(5);
Console.WriteLine($"Distance: {distance}");
var time = Second.From(4);
Console.WriteLine($"Time: {time}");
var speed = Ops.Divide(distance, time);
Console.WriteLine($"Speed: {speed}");
var anotherDistance = Kilometer.From(0.3f);
Console.WriteLine($"Another distance: {anotherDistance}");
Console.WriteLine($"Total distance: {Ops.Add<Meter, Kilometer, Meter>(distance, anotherDistance)}");
var speed1 = Meter.From(20).Divide(Second.From(1));
Console.WriteLine($"Speed 1: {speed1}");
var speed2 = Kilometer.From(5).Divide(Minute.From(1));
Console.WriteLine($"Speed 2: {speed2}");
var added = speed1.Add(speed2);
Console.WriteLine($"Their sum: {added}");
var sideOfHouse1 = Meter.From(200);
var sideOfHouse2 = Kilometer.From(0.5f);
Console.WriteLine($"Side size of house 1: {sideOfHouse1}");
Console.WriteLine($"Side size of house 2: {sideOfHouse2}");
var area1 = sideOfHouse1.Square();
var area2 = sideOfHouse2.Square();
Console.WriteLine($"Area of house 1: {area1}");
Console.WriteLine($"Area of house 2: {area2}");
var totalArea = area1.Add(area2);
Console.WriteLine($"Total area: {totalArea}");
var outerHouse = Mile.From(0.35f).Square();
var areaOf2and3 = area2.Add(outerHouse);
Console.WriteLine($"Area of 2nd and 3rd house: {areaOf2and3}");
var areaOf2and3rev = outerHouse.Add(area2);
Console.WriteLine($"Area of 2nd and 3rd house in miles: {areaOf2and3rev}");
public record struct Unit<T, TBase>(float Float)
where TBase : struct, IBaseUnit<TBase>
where T : struct, IBaseUnit<TBase>
{
public override string ToString() => $"{Float} {new T()}";
}
public static class Ops
{
public static Unit<Div<T1, T2, T1Base, T2Base>, Div<T1Base, T2Base, T1Base, T2Base>> Divide<T1, T2, T1Base, T2Base>(this Unit<T1, T1Base> a, Unit<T2, T2Base> b)
where T1Base : struct, IBaseUnit<T1Base>
where T2Base : struct, IBaseUnit<T2Base>
where T1 : struct, IBaseUnit<T1Base>
where T2 : struct, IBaseUnit<T2Base>
=> new(a.Float / b.Float);
public static Unit<T1, TBase> Add<T1, T2, TBase>(this Unit<T1, TBase> a, Unit<T2, TBase> b)
where TBase : struct, IBaseUnit<TBase>
where T1 : struct, IBaseUnit<TBase>
where T2 : struct, IBaseUnit<TBase>
=> new((a.Float * new T1().Base + b.Float * new T2().Base) / new T1().Base);
public static Unit<Squared<T, TBase>, Squared<TBase, TBase>> Square<T, TBase>(this Unit<T, TBase> a)
where TBase : struct, IBaseUnit<TBase>
where T : struct, IBaseUnit<TBase>
=> new(a.Float * a.Float);
}
public interface IBaseUnit<T>// : IUnit where T : IUnit
{
float Base { get; }
}
public struct Meter : IBaseUnit<Meter>
{
public override string ToString() => "m";
public float Base => 1;
public static Unit<Meter, Meter> From(float a) => new(a);
}
public struct Kilometer : IBaseUnit<Meter>
{
public override string ToString() => "km";
public float Base => 1000;
public static Unit<Kilometer, Meter> From(float a) => new(a);
}
public struct Mile : IBaseUnit<Meter>
{
public override string ToString() => "mile";
public float Base => 1600;
public static Unit<Mile, Meter> From(float a) => new(a);
}
public struct Second : IBaseUnit<Second>
{
public override string ToString() => "s";
public float Base => 1;
public static Unit<Second, Second> From(float a) => new(a);
}
public struct Minute : IBaseUnit<Second>
{
public override string ToString() => "min";
public float Base => 60;
public static Unit<Minute, Second> From(float a) => new(a);
}
public struct Squared<T, TBase>
: IBaseUnit<Squared<TBase, TBase>>
where T : struct, IBaseUnit<TBase>
where TBase : struct, IBaseUnit<TBase>
{
public float Base => new T().Base * new T().Base;
public override string ToString() => $"({new T()})^2";
}
public struct Div<T1, T2, T1Base, T2Base>
: IBaseUnit<Div<T1Base, T2Base, T1Base, T2Base>>
where T1Base : struct, IBaseUnit<T1Base>
where T2Base : struct, IBaseUnit<T2Base>
where T1 : struct, IBaseUnit<T1Base>
where T2 : struct, IBaseUnit<T2Base>
{
public float Base => new T1().Base / new T2().Base;
public override string ToString() => $"({new T1()}/{new T2()})";
}
Distance: 5 m
Time: 4 s
Speed: 1.25 (m/s)
Another distance: 0.3 km
Total distance: 305 m
Speed 1: 20 (m/s)
Speed 2: 5 (km/min)
Their sum: 103.33333 (m/s)
Side size of house 1: 200 m
Side size of house 2: 0.5 km
Area of house 1: 40000 (m)^2
Area of house 2: 0.25 (km)^2
Total area: 290000 (m)^2
Area of 2nd and 3rd house: 0.5636 (km)^2
Area of 2nd and 3rd house in miles: 0.22015625 (mile)^2
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment