using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Runtime.Serialization; using System.Text; namespace Raytheon.Units { /// /// This class represents energy. /// /// It has no constructors. Instead, it provides multiple methods for creating objects of this /// type. Those methods are of the form FromXXX, where XXX is a unit (e.g. FromJoulesPerCmSqrd). /// /// Properties (e.g. JoulesPerCmSqrd) are provided to convert the value to other units and return /// as type double. /// [Serializable] [DataContract] public class Energy { public enum Unit { JoulesPerCmSqrd, MillijoulesPerCmSqrd } public static IDictionary> UnitAbbreviations = new Dictionary>() { {Unit.JoulesPerCmSqrd, new List(){ "J/cm^2" } }, {Unit.MillijoulesPerCmSqrd, new List(){ "mJ/cm^2" } }, }; private const Unit DefaultUnits = Unit.JoulesPerCmSqrd; [DataMember(Name = "Energy", IsRequired = true)] private double _energy; // joules/centimeter^2 // map: unit => abbreviation, conversion method and property private static IDictionary> _unitInfo = new Dictionary>() { { Unit.JoulesPerCmSqrd, new UnitInfo(UnitAbbreviations[Unit.JoulesPerCmSqrd], FromJoulesPerCmSqrd, typeof(Energy).GetProperty("JoulesPerCmSqrd").GetGetMethod()) }, { Unit.MillijoulesPerCmSqrd, new UnitInfo(UnitAbbreviations[Unit.MillijoulesPerCmSqrd], FromMillijoulesPerCmSqrd, typeof(Energy).GetProperty("MillijoulesPerCmSqrd").GetGetMethod()) } }; /// /// Prevents a default instance of the class from being created. /// Use FromXXX methods to create objects of this type. /// /// No one should be calling this, it is only here to prevent users from creating default object private Energy() { throw new InvalidOperationException("No one should be calling this, it is only here to prevent users from creating default object"); } /// /// ctor used by this class to create objects in FromXXX methods /// /// The energy - joules/cm^2. private Energy(double energy) { _energy = energy; } #region conversion properties /// /// Returns joules/cm^2 as type double /// /// /// joules/cm^2 /// public double JoulesPerCmSqrd { get { return _energy; } } /// /// Returns joules/cm^2 as type double /// /// /// joules/cm^2 /// public double MillijoulesPerCmSqrd { get { return _energy * 1000; } } #endregion #region creation methods /// /// Returns Energy object interpreting passed value as joules/cm^2 /// /// joules/cm^2 /// public static Energy FromJoulesPerCmSqrd(double joulesPerCmSqrd) { return new Energy(joulesPerCmSqrd); } /// /// Returns Energy object interpreting passed value as joules/cm^2 /// /// joules/cm^2 /// public static Energy FromMillijoulesPerCmSqrd(double joulesPerCmSqrd) { return new Energy(joulesPerCmSqrd / 1000); } #endregion public override bool Equals(object obj) { Energy e = obj as Energy; return (e == null) ? false : (this._energy == e._energy); } public override int GetHashCode() { return _energy.GetHashCode(); } #region binary operators // not implementing %, &, |, ^, <<, >> public static Energy operator +(Energy left, Energy right) { if (null == left) throw new ArgumentNullException("left", "Cannot add a null Energy"); if (null == right) throw new ArgumentNullException("right", "Cannot add null Energy"); return new Energy(left._energy + right._energy); } public static Energy operator -(Energy left, Energy right) { if (null == left) throw new ArgumentNullException("left", "Cannot subtract a null Energy"); if (null == right) throw new ArgumentNullException("right", "Cannot subtract a null Energy"); return new Energy(left._energy - right._energy); } public static Energy operator *(Energy energy, double scalar) { if (null == energy) throw new ArgumentNullException("energy", "Cannot multiply a null Energy"); return new Energy(energy._energy * scalar); } public static Energy operator *(double scalar, Energy energy) { if (null == energy) throw new ArgumentNullException("energy", "Cannot multiply a null Energy"); return new Energy(scalar * energy._energy); } public static Energy operator /(Energy energy, double scalar) { if (null == energy) throw new ArgumentNullException("energy", "Cannot divide a null Energy"); if (0.0 == scalar) throw new DivideByZeroException("Cannot divide Energy by 0"); return new Energy(energy._energy / scalar); } #endregion #region comparison operators public static bool operator ==(Energy left, Energy 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._energy == right._energy; } } return bReturn; } public static bool operator !=(Energy left, Energy right) { return !(left == right); } public static bool operator <(Energy left, Energy right) { if (null == left) throw new ArgumentNullException("left", "Cannot compare null Energy"); if (null == right) throw new ArgumentNullException("right", "Cannot compare null Energy"); return (left._energy < right._energy); } public static bool operator >(Energy left, Energy right) { if (null == left) throw new ArgumentNullException("left", "Cannot compare null Energy"); if (null == right) throw new ArgumentNullException("right", "Cannot compare null Energy"); return (left._energy > right._energy); } public static bool operator <=(Energy left, Energy right) { if (null == left) throw new ArgumentNullException("left", "Cannot compare null Energy"); if (null == right) throw new ArgumentNullException("right", "Cannot compare null Energy"); return (left._energy <= right._energy); } public static bool operator >=(Energy left, Energy right) { if (null == left) throw new ArgumentNullException("left", "Cannot compare null Energy"); if (null == right) throw new ArgumentNullException("right", "Cannot compare null Energy"); return (left._energy >= right._energy); } #endregion #region operators with other classes // no operators right now #endregion #region parsing public static Energy Parse(string s) { return Common.Parse(s, _unitInfo); } public static bool TryParse(string s, out Energy value) { try { value = Energy.Parse(s); return true; } catch (Exception) { value = null; return false; } } #endregion /// /// 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]}"; } } }