Note that there are some explanatory texts on larger screens.

plurals
  1. POUnits of measure in C# - almost
    text
    copied!<p>Inspired by <a href="https://stackoverflow.com/questions/40845/how-do-f-units-of-measurement-work">Units of Measure in F#</a>, and despite asserting (<a href="https://stackoverflow.com/questions/39492/where-can-f-actually-save-time-and-money#71112">here</a>) that you couldn't do it in C#, I had an idea the other day which I've been playing around with.</p> <pre><code>namespace UnitsOfMeasure { public interface IUnit { } public static class Length { public interface ILength : IUnit { } public class m : ILength { } public class mm : ILength { } public class ft : ILength { } } public class Mass { public interface IMass : IUnit { } public class kg : IMass { } public class g : IMass { } public class lb : IMass { } } public class UnitDouble&lt;T&gt; where T : IUnit { public readonly double Value; public UnitDouble(double value) { Value = value; } public static UnitDouble&lt;T&gt; operator +(UnitDouble&lt;T&gt; first, UnitDouble&lt;T&gt; second) { return new UnitDouble&lt;T&gt;(first.Value + second.Value); } //TODO: minus operator/equality } } </code></pre> <p>Example usage:</p> <pre><code>var a = new UnitDouble&lt;Length.m&gt;(3.1); var b = new UnitDouble&lt;Length.m&gt;(4.9); var d = new UnitDouble&lt;Mass.kg&gt;(3.4); Console.WriteLine((a + b).Value); //Console.WriteLine((a + c).Value); &lt;-- Compiler says no </code></pre> <p>The next step is trying to implement conversions (snippet):</p> <pre><code>public interface IUnit { double toBase { get; } } public static class Length { public interface ILength : IUnit { } public class m : ILength { public double toBase { get { return 1.0;} } } public class mm : ILength { public double toBase { get { return 1000.0; } } } public class ft : ILength { public double toBase { get { return 0.3048; } } } public static UnitDouble&lt;R&gt; Convert&lt;T, R&gt;(UnitDouble&lt;T&gt; input) where T : ILength, new() where R : ILength, new() { double mult = (new T() as IUnit).toBase; double div = (new R() as IUnit).toBase; return new UnitDouble&lt;R&gt;(input.Value * mult / div); } } </code></pre> <p>(I would have liked to avoid instantiating objects by using static, but as we all know you <a href="https://stackoverflow.com/questions/259026/why-doesnt-c-allow-static-methods-to-implement-an-interface">can't declare a static method in an interface</a>) You can then do this:</p> <pre><code>var e = Length.Convert&lt;Length.mm, Length.m&gt;(c); var f = Length.Convert&lt;Length.mm, Mass.kg&gt;(d); &lt;-- but not this </code></pre> <p>Obviously, there is a gaping hole in this, compared to F# Units of measure (I'll let you work it out).</p> <p>Oh, the question is: what do you think of this? Is it worth using? Has someone else already done better?</p> <p><strong>UPDATE</strong> for people interested in this subject area, <a href="http://www.cs.utexas.edu/users/novak/units95.pdf" rel="nofollow noreferrer">here</a> is a link to a paper from 1997 discussing a different kind of solution (not specifically for C#)</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload