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 Temperature { 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; private const double CtoF_Offset = 32.0; private const double KtoC_Offset = 273.15; [DataMember(Name = "Temperature", IsRequired = true)] private double _temperature; // degrees C // map: unit => abbreviation, conversion method and property private static IDictionary> _unitInfo = new Dictionary>() { { Unit.DegreesC, new UnitInfo(UnitAbbreviations[Unit.DegreesC], FromDegreesC, typeof(Temperature).GetProperty("DegreesC").GetGetMethod()) }, { Unit.DegreesF, new UnitInfo(UnitAbbreviations[Unit.DegreesF], FromDegreesF, typeof(Temperature).GetProperty("DegreesF").GetGetMethod()) }, { Unit.DegreesK, new UnitInfo(UnitAbbreviations[Unit.DegreesK], FromDegreesK, typeof(Temperature).GetProperty("DegreesK").GetGetMethod()) } }; private Temperature() { throw new InvalidOperationException("No one should be calling this, it is only here to prevent users from creating default object"); } private Temperature(double temperature) { _temperature = temperature; } #region output properties public double DegreesC { get { return _temperature; } } public double DegreesF { get { return (_temperature / CdegreesPerFdegree) + CtoF_Offset; } } public double DegreesK { get { return DegreesC + KtoC_Offset; } } #endregion #region creation methods public static Temperature FromDegreesC(double temperature) { return new Temperature(temperature); } public static Temperature FromDegreesF(double temperature) { return new Temperature((temperature - CtoF_Offset) * CdegreesPerFdegree); } public static Temperature FromDegreesK(double temperature) { return FromDegreesC(temperature - KtoC_Offset); } #endregion #region add delta methods public void Add(TemperatureDelta delta) { if (delta == null) { throw new ArgumentNullException("delta"); } _temperature += delta.DegreesC; } public void AddDegreesC(double delta) { _temperature += TemperatureDelta.FromDegreesC(delta).DegreesC; } public void AddDegreesF(double delta) { _temperature += TemperatureDelta.FromDegreesF(delta).DegreesC; } public void AddDegreesK(double delta) { _temperature += TemperatureDelta.FromDegreesK(delta).DegreesC; } #endregion #region binary operators public static Temperature operator +(Temperature left, TemperatureDelta right) { if (null == left) throw new ArgumentNullException("left", "Cannot add a null Temperature"); if (null == right) throw new ArgumentNullException("right", "Cannot add null TemperatureDelta"); return new Temperature(left.DegreesC + right.DegreesC); } public static Temperature operator +(TemperatureDelta left, Temperature right) { if (null == left) throw new ArgumentNullException("left", "Cannot add a null TemperatureDelta"); if (null == right) throw new ArgumentNullException("right", "Cannot add null Temperature"); return new Temperature(left.DegreesC + right.DegreesC); } public static TemperatureDelta operator -(Temperature left, Temperature right) { if (null == left) throw new ArgumentNullException("left", "Cannot add a null Temperature"); if (null == right) throw new ArgumentNullException("right", "Cannot add null Temperature"); return TemperatureDelta.FromDegreesC(left.DegreesC - right.DegreesC); } public static Temperature operator -(Temperature left, TemperatureDelta right) { if (null == left) throw new ArgumentNullException("left", "Cannot add a null Temperature"); if (null == right) throw new ArgumentNullException("right", "Cannot add null TemperatureDelta"); return Temperature.FromDegreesC(left.DegreesC - right.DegreesC); } #endregion #region comparison operators public static bool operator ==(Temperature left, Temperature right) { bool bReturn = false; if (object.ReferenceEquals(left, null)) { if (object.ReferenceEquals(right, null)) { //both are null, so we are == bReturn = true; } } else { if (!object.ReferenceEquals(left, null) && !object.ReferenceEquals(right, null)) { bReturn = left._temperature == right._temperature; } } return bReturn; } public static bool operator !=(Temperature left, Temperature right) { return !(left == right); } public static bool operator <(Temperature left, Temperature right) { if (null == left) throw new ArgumentNullException("left", "Cannot compare null Temperature"); if (null == right) throw new ArgumentNullException("right", "Cannot compare null Temperature"); return (left._temperature < right._temperature); } public static bool operator >(Temperature left, Temperature right) { if (null == left) throw new ArgumentNullException("left", "Cannot compare null Temperature"); if (null == right) throw new ArgumentNullException("right", "Cannot compare null Temperature"); return (left._temperature > right._temperature); } public static bool operator <=(Temperature left, Temperature right) { if (null == left) throw new ArgumentNullException("left", "Cannot compare null Temperature"); if (null == right) throw new ArgumentNullException("right", "Cannot compare null Temperature"); return (left._temperature <= right._temperature); } public static bool operator >=(Temperature left, Temperature right) { if (null == left) throw new ArgumentNullException("left", "Cannot compare null Temperature"); if (null == right) throw new ArgumentNullException("right", "Cannot compare null Temperature"); return (left._temperature >= right._temperature); } #endregion #region parsing public static Temperature Parse(string s) { return Common.Parse(s, _unitInfo); } public static bool TryParse(string s, out Temperature value) { try { value = Temperature.Parse(s); return true; } catch (Exception) { value = null; return false; } } #endregion #region Object overrides public override bool Equals(object obj) { Temperature t = obj as Temperature; return (t == null) ? false : (this._temperature == t._temperature); } public override int GetHashCode() { return _temperature.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 } }