Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>I thought this was an interesting little problem, so I decided to see how nicely this could be wrapped up into a generic implementation. This isn't well-tested (and doesn't handle all error cases - such as if you don't register the conversion for a particular unit type, then pass that in), but it might be useful. The focus was on making the inherited class (<code>TemperatureConverter</code>) as tidy as possible.</p> <pre><code>/// &lt;summary&gt; /// Generic conversion class for converting between values of different units. /// &lt;/summary&gt; /// &lt;typeparam name="TUnitType"&gt;The type representing the unit type (eg. enum)&lt;/typeparam&gt; /// &lt;typeparam name="TValueType"&gt;The type of value for this unit (float, decimal, int, etc.)&lt;/typeparam&gt; abstract class UnitConverter&lt;TUnitType, TValueType&gt; { /// &lt;summary&gt; /// The base unit, which all calculations will be expressed in terms of. /// &lt;/summary&gt; protected static TUnitType BaseUnit; /// &lt;summary&gt; /// Dictionary of functions to convert from the base unit type into a specific type. /// &lt;/summary&gt; static ConcurrentDictionary&lt;TUnitType, Func&lt;TValueType, TValueType&gt;&gt; ConversionsTo = new ConcurrentDictionary&lt;TUnitType, Func&lt;TValueType, TValueType&gt;&gt;(); /// &lt;summary&gt; /// Dictionary of functions to convert from the specified type into the base unit type. /// &lt;/summary&gt; static ConcurrentDictionary&lt;TUnitType, Func&lt;TValueType, TValueType&gt;&gt; ConversionsFrom = new ConcurrentDictionary&lt;TUnitType, Func&lt;TValueType, TValueType&gt;&gt;(); /// &lt;summary&gt; /// Converts a value from one unit type to another. /// &lt;/summary&gt; /// &lt;param name="value"&gt;The value to convert.&lt;/param&gt; /// &lt;param name="from"&gt;The unit type the provided value is in.&lt;/param&gt; /// &lt;param name="to"&gt;The unit type to convert the value to.&lt;/param&gt; /// &lt;returns&gt;The converted value.&lt;/returns&gt; public TValueType Convert(TValueType value, TUnitType from, TUnitType to) { // If both From/To are the same, don't do any work. if (from.Equals(to)) return value; // Convert into the base unit, if required. var valueInBaseUnit = from.Equals(BaseUnit) ? value : ConversionsFrom[from](value); // Convert from the base unit into the requested unit, if required var valueInRequiredUnit = to.Equals(BaseUnit) ? valueInBaseUnit : ConversionsTo[to](valueInBaseUnit); return valueInRequiredUnit; } /// &lt;summary&gt; /// Registers functions for converting to/from a unit. /// &lt;/summary&gt; /// &lt;param name="convertToUnit"&gt;The type of unit to convert to/from, from the base unit.&lt;/param&gt; /// &lt;param name="conversionTo"&gt;A function to convert from the base unit.&lt;/param&gt; /// &lt;param name="conversionFrom"&gt;A function to convert to the base unit.&lt;/param&gt; protected static void RegisterConversion(TUnitType convertToUnit, Func&lt;TValueType, TValueType&gt; conversionTo, Func&lt;TValueType, TValueType&gt; conversionFrom) { if (!ConversionsTo.TryAdd(convertToUnit, conversionTo)) throw new ArgumentException("Already exists", "convertToUnit"); if (!ConversionsFrom.TryAdd(convertToUnit, conversionFrom)) throw new ArgumentException("Already exists", "convertToUnit"); } } </code></pre> <p>The generic type args are for an enum that represents the units, and the type for the value. To use it, you just have to inherit from this class (providing the types) and register some lambdas to do the conversion. Here's an example for temperature (with some dummy calculations):</p> <pre><code>enum Temperature { Celcius, Fahrenheit, Kelvin } class TemperatureConverter : UnitConverter&lt;Temperature, float&gt; { static TemperatureConverter() { BaseUnit = Temperature.Celcius; RegisterConversion(Temperature.Fahrenheit, v =&gt; v * 2f, v =&gt; v * 0.5f); RegisterConversion(Temperature.Kelvin, v =&gt; v * 10f, v =&gt; v * 0.05f); } } </code></pre> <p>And then using it is pretty simple:</p> <pre><code>var converter = new TemperatureConverter(); Console.WriteLine(converter.Convert(1, Temperature.Celcius, Temperature.Fahrenheit)); Console.WriteLine(converter.Convert(1, Temperature.Fahrenheit, Temperature.Celcius)); Console.WriteLine(converter.Convert(1, Temperature.Celcius, Temperature.Kelvin)); Console.WriteLine(converter.Convert(1, Temperature.Kelvin, Temperature.Celcius)); Console.WriteLine(converter.Convert(1, Temperature.Kelvin, Temperature.Fahrenheit)); Console.WriteLine(converter.Convert(1, Temperature.Fahrenheit, Temperature.Kelvin)); </code></pre>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

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