Last active
December 20, 2021 16:03
-
-
Save WhiteBlackGoose/f24353b4d8b0a27860acfbd73056e020 to your computer and use it in GitHub Desktop.
Advanced measurement units
This file contains hidden or 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; | |
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()})"; | |
} |
This file contains hidden or 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
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