using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Runtime.Serialization; using System.Diagnostics.CodeAnalysis; namespace Raytheon.Units { [Serializable] [DataContract] public class TemperatureDelta { public enum Unit { DegreesC, DegreesF, DegreesK } public static IDictionary> UnitAbbreviations = new Dictionary>() { {Unit.DegreesC, new List(){ "C" } }, {Unit.DegreesF, new List(){ "F" } }, {Unit.DegreesK, new List(){ "K" } }, }; private const Unit DefaultUnits = Unit.DegreesC; private const double CdegreesPerFdegree = 5.0 / 9.0; [DataMember(Name = "Delta", IsRequired = true)] private double _delta; // degrees C or K // map: unit => abbreviation, conversion method and property private static IDictionary> _unitInfo = new Dictionary>() { { Unit.DegreesC, new UnitInfo(UnitAbbreviations[Unit.DegreesC], FromDegreesC, typeof(TemperatureDelta).GetProperty("DegreesC").GetGetMethod()) }, { Unit.DegreesF, new UnitInfo(UnitAbbreviations[Unit.DegreesF], FromDegreesF, typeof(TemperatureDelta).GetProperty("DegreesF").GetGetMethod()) }, { Unit.DegreesK, new UnitInfo(UnitAbbreviations[Unit.DegreesK], FromDegreesK, typeof(TemperatureDelta).GetProperty("DegreesK").GetGetMethod()) } }; private TemperatureDelta() { throw new InvalidOperationException("No one should be calling this, it is only here to prevent users from creating default object"); } private TemperatureDelta(double delta) { _delta = delta; } #region output properties public double DegreesC { get { return _delta; } } public double DegreesF { get { return _delta / CdegreesPerFdegree; } } public double DegreesK { get { return _delta; } } #endregion #region creation methods public static TemperatureDelta FromDegreesC(double temperature) { return new TemperatureDelta(temperature); } public static TemperatureDelta FromDegreesF(double temperature) { return new TemperatureDelta(temperature * CdegreesPerFdegree); } public static TemperatureDelta FromDegreesK(double temperature) { return new TemperatureDelta(temperature); } #endregion // binary operators are in Temperature class #region comparison operators public static bool operator <(TemperatureDelta left, TemperatureDelta right) { if (null == left) throw new ArgumentNullException("left", "Cannot compare null TemperatureDelta"); if (null == right) throw new ArgumentNullException("right", "Cannot compare null TemperatureDelta"); return (left._delta < right._delta); } public static bool operator >(TemperatureDelta left, TemperatureDelta right) { if (null == left) throw new ArgumentNullException("left", "Cannot compare null TemperatureDelta"); if (null == right) throw new ArgumentNullException("right", "Cannot compare null TemperatureDelta"); return (left._delta > right._delta); } public static bool operator <=(TemperatureDelta left, TemperatureDelta right) { if (null == left) throw new ArgumentNullException("left", "Cannot compare null TemperatureDelta"); if (null == right) throw new ArgumentNullException("right", "Cannot compare null TemperatureDelta"); return (left._delta <= right._delta); } public static bool operator >=(TemperatureDelta left, TemperatureDelta right) { if (null == left) throw new ArgumentNullException("left", "Cannot compare null TemperatureDelta"); if (null == right) throw new ArgumentNullException("right", "Cannot compare null TemperatureDelta"); return (left._delta >= right._delta); } #endregion #region parsing public static TemperatureDelta Parse(string s) { return Common.Parse(s, _unitInfo); } public static bool TryParse(string s, out TemperatureDelta value) { try { value = TemperatureDelta.Parse(s); return true; } catch (Exception) { value = null; return false; } } #endregion #region Object overrides public override bool Equals(object obj) { TemperatureDelta d = obj as TemperatureDelta; return (d == null) ? false : (this._delta == d._delta); } public override int GetHashCode() { return _delta.GetHashCode(); } /// /// Returns a string appended with default units (e.g. "1.23 m/sec^2"). /// /// /// A string that represents this instance /// public override string ToString() { return ToString(DefaultUnits); } /// /// overload that returns a string appended with specified units (e.g. "1.23 ft/sec^2"). /// /// /// public string ToString(Unit units) { double value = (double)_unitInfo[units].PropertyGetter.Invoke(this, null); return $"{value} {_unitInfo[units].Abbreviation[0]}"; } #endregion } }