Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

A C# Temperature Struct

0.00/5 (No votes)
6 Jan 2012 1  
A temperature struct in C#

Microsoft loves using temperature in .NET examples. See here and here.

So, I decided to combine them all into a nice structure that implements IFormattable, IComparable, IEquatable<t>, etc. That way, they don't have to keep rewriting it themselves.

The code also gives some good examples on operator overloading. Have fun.

using System;
using System.Globalization;

/// <summary>
/// Options for temperature measurement units.
/// </summary>
public enum TemperatureUnit
{
    /// <summary>
    /// The SI base unit of thermodynamic temperature,
    /// equal in magnitude to the degree Celsius.
    /// </summary>
    Kelvin,

    /// <summary>
    /// A scale of temperature on which water freezes
    /// at 0° and boils at 100° under standard conditions.
    /// </summary>
    Celsius,

    /// <summary>
    /// A scale of temperature on which water freezes at 32°
    /// and boils at 212° under standard conditions.
    /// </summary>
    Fahrenheit
}

/// <summary>
/// A temperature value.
/// </summary>
public struct Temperature : IFormattable, IComparable, 
       IComparable<Temperature>, IEquatable<Temperature>
{
    private double _Kelvin;

    /// <summary>
    /// Creates a new temperature with the specified value in Kelvin.
    /// </summary>
    /// <param name="kelvin">The value of the temperature.</param>
    public Temperature(double kelvin) : this() { _Kelvin = kelvin; }

    /// <summary>
    /// Creates a new temperature with the specified value in the
    /// specified unit of measurement.
    /// </summary>
    /// <param name="temperature">The value of the temperature.</param>
    /// <param name="unit">The unit of measurement that defines how
    /// the <paramref name="temperature"/> value is used.</param>
    public Temperature(double temperature, TemperatureUnit unit)
        : this()
    {
        switch (unit)
        {
            case TemperatureUnit.Kelvin:
                _Kelvin = temperature;
                break;
            case TemperatureUnit.Celsius:
                Celsius = temperature;
                break;
            case TemperatureUnit.Fahrenheit:
                Fahrenheit = temperature;
                break;
            default:
                throw new ArgumentException(
                  "The temperature unit '" + unit.ToString() + "' is unknown.");
        }
    }

    /// <summary>
    /// Gets or sets the temperature value in Kelvin.
    /// </summary>
    public double Kelvin
    {
        get { return _Kelvin; }
        set { _Kelvin = value; }
    }

    /// <summary>
    /// Gets or sets the temperature value in Celsius.
    /// </summary>
    public double Celsius
    {
        get { return KelvinToCelsius(_Kelvin); }
        set { _Kelvin = CelsiusToKelvin(value); }
    }

    /// <summary>
    /// Gets or sets the temperature value in Fahrenheit.
    /// </summary>
    public double Fahrenheit
    {
        get { return KelvinToFahrenheit(_Kelvin); }
        set { _Kelvin = FahrenheitToKelvin(value); }
    }

    /// <summary>
    /// Gets the temperature value in the specified unit of measurement.
    /// </summary>
    /// <param name="unit">The unit of measurement
    /// in which the temperature should be retrieved.</param>
    /// <returns>The temperature value in the specified 
    /// <paramref name="unit"/>.</returns>
    public double ValueIn(TemperatureUnit unit)
    {
        switch (unit)
        {
            case TemperatureUnit.Kelvin: return _Kelvin;
            case TemperatureUnit.Celsius: return Celsius;
            case TemperatureUnit.Fahrenheit: return Fahrenheit;
            default: throw new ArgumentException(
               "Unknown temperature unit '" + unit.ToString() + "'.");
        }
    }

    /// <summary>
    /// Returns a string representation of the temperature value.
    /// </summary>
    /// <param name="format">
    /// A single format specifier that indicates how to format the value of this
    /// temperature. The format parameter can be "G", 
    /// "C", "F", or "K". If format
    /// is null or the empty string (""), "G" is used.
    /// </param>
    /// <param name="provider">
    /// An IFormatProvider reference that supplies culture-specific formatting
    /// services.
    /// </param>
    /// <returns>A string representation of the temperature.</returns>
    /// <exception cref="FormatException">
    /// The value of format is not null, the empty string (""), "G", "C", "F", or
    /// "K".
    /// </exception>
    public string ToString(string format, IFormatProvider provider)
    {
        if (String.IsNullOrEmpty(format)) format = "G";
        if (provider == null) provider = CultureInfo.CurrentCulture;

        switch (format.ToUpperInvariant())
        {
            case "G":
            case "C":
                return Celsius.ToString("F2", provider) + " °C";
            case "F":
                return Fahrenheit.ToString("F2", provider) + " °F";
            case "K":
                return _Kelvin.ToString("F2", provider) + " K";
            default:
                throw new FormatException(
                      String.Format("The {0} format string is not supported.", format));
        }
    }

    /// <summary>
    /// Returns a string representation of the temperature value.
    /// </summary>
    /// <param name="format">
    /// A single format specifier that indicates how to format the value of this
    /// temperature. The format parameter can be "G", 
    /// "C", "F", or "K". If format
    /// is null or the empty string (""), "G" is used.
    /// </param>
    /// <returns>A string representation of the temperature.</returns>
    /// <exception cref="FormatException">
    /// The value of format is not null, 
    /// the empty string (""), "G", "C", "F", or
    /// "K".
    /// </exception>
    public string ToString(string format)
    {
        return ToString(format, null);
    }

    /// <summary>
    /// Returns a string representation of the temperature value.
    /// </summary>
    /// <returns>A string representation of the temperature.</returns>
    public override string ToString()
    {
        return ToString(null, null);
    }

    /// <summary>
    /// Returns a string representation of the temperature value.
    /// </summary>
    /// <param name="unit">
    /// The temperature unit as which the temperature value should be displayed.
    /// </param>
    /// <param name="provider">
    /// An IFormatProvider reference that supplies culture-specific formatting
    /// services.
    /// </param>
    /// <returns>A string representation of the temperature.</returns>
    public string ToString(TemperatureUnit unit, IFormatProvider provider)
    {
        switch (unit)
        {
            case TemperatureUnit.Celsius:
                return ToString("C", provider);
            case TemperatureUnit.Fahrenheit:
                return ToString("F", provider);
            case TemperatureUnit.Kelvin:
                return ToString("K", provider);
            default:
                throw new FormatException("The temperature unit '" + 
                      unit.ToString() + "' is unknown.");
        }
    }

    /// <summary>
    /// Returns a string representation of the temperature value.
    /// </summary>
    /// <param name="unit">
    /// The temperature unit as which the temperature value should be displayed.
    /// </param>
    /// <returns>A string representation of the temperature.</returns>
    public string ToString(TemperatureUnit unit)
    {
        return ToString(unit, null);
    }

    /// <summary>
    /// Compares this instance to a specified Temperature object and returns an indication
    /// of their relative values.
    /// </summary>
    /// <param name="value">A Temperature object
    ///    to compare to this instance.</param>
    /// <returns>
    /// A signed number indicating the relative values of this instance and value.
    /// Value Description A negative integer This instance is less than value. Zero
    /// This instance is equal to value. A positive integer This instance is greater
    /// than value.
    /// </returns>
    public int CompareTo(Temperature value)
    {
        return _Kelvin.CompareTo(value._Kelvin);
    }

    /// <summary>
    /// Compares this instance to a specified object and returns an indication of
    /// their relative values.
    /// </summary>
    /// <param name="value">An object to compare, or null.</param>
    /// <returns>
    /// A signed number indicating the relative values of this instance and value.
    /// Value Description A negative integer This instance is less than value. Zero
    /// This instance is equal to value. A positive integer This instance is greater
    /// than value, or value is null.
    /// </returns>
    /// <exception cref="ArgumentException">
    /// The value is not a Temperature.
    /// </exception>
    public int CompareTo(object value)
    {
        if (value == null) return 1;
        if (!(value is Temperature)) throw new ArgumentException();
            return CompareTo((Temperature)value);
    }

    /// <summary>
    /// Determines whether or not the given temperature is considered equal to this instance.
    /// </summary>
    /// <param name="value">The temperature to compare to this instance.</param>
    /// <returns>True if the temperature is considered equal
    ///    to this instance. Otherwise, false.</returns>
    public bool Equals(Temperature value)
    {
        return _Kelvin == value._Kelvin;
    }

    /// <summary>
    /// Determines whether or not the given object is considered equal to the temperature.
    /// </summary>
    /// <param name="value">The object to compare to the temperature.</param>
    /// <returns>True if the object is considered equal
    ///     to the temperature. Otherwise, false.</returns>
    public override bool Equals(object value)
    {
        if (value == null) return false;
        if (!(value is Temperature)) return false;

        return Equals((Temperature)value);
    }

    /// <summary>
    /// Returns the hash code for this instance.
    /// </summary>
    /// <returns>A 32-bit signed integer hash code.</returns>
    public override int GetHashCode()
    {
        return _Kelvin.GetHashCode();
    }

    /// <summary>
    /// Determines the equality of two temperatures.
    /// </summary>
    /// <param name="t1">The first temperature to be compared.</param>
    /// <param name="t2">The second temperature to be compared.</param>
    /// <returns>True if the temperatures are equal. Otherwise, false.</returns>
    public static bool operator ==(Temperature t1, Temperature t2)
    {
        return t1.Equals(t2);
    }

    /// <summary>
    /// Determines the inequality of two temperatures.
    /// </summary>
    /// <param name="t1">The first temperature to be compared.</param>
    /// <param name="t2">The second temperature to be compared.</param>
    /// <returns>True if the temperatures are NOT equal. Otherwise, false.</returns>
    public static bool operator !=(Temperature t1, Temperature t2)
    {
        return !t1.Equals(t2);
    }

    /// <summary>
    /// Determines whether one temperature is considered greater than another.
    /// </summary>
    /// <param name="t1">The first temperature to be compared.</param>
    /// <param name="t2">The second temperature to be compared.</param>
    /// <returns>True if the first temperature is greater than the second. 
    /// Otherwise, false.</returns>
    public static bool operator >(Temperature t1, Temperature t2)
    {
        return t1._Kelvin > t2._Kelvin;
    }

    /// <summary>
    /// Determines whether one temperature is considered less than another.
    /// </summary>
    /// <param name="t1">The first temperature to be compared.</param>
    /// <param name="t2">The second temperature to be compared.</param>
    /// <returns>True if the first temperature is less than the second. 
    /// Otherwise, false.</returns>
    public static bool operator <(Temperature t1, Temperature t2)
    {
        return t1._Kelvin < t2._Kelvin;
    }

    /// <summary>
    /// Determines whether one temperature is considered greater to or equal to another.
    /// </summary>
    /// <param name="t1">The first temperature to be compared.</param>
    /// <param name="t2">The second temperature to be compared.</param>
    /// <returns>
    /// True if the first temperature is greater to or equal to the second. Otherwise, false.
    /// </returns>
    public static bool operator >=(Temperature t1, Temperature t2)
    {
        return t1._Kelvin >= t2._Kelvin;
    }

    /// <summary>
    /// Determines whether one temperature is considered less than or equal to another.
    /// </summary>
    /// <param name="t1">The first temperature to be compared.</param>
    /// <param name="t2">The second temperature to be compared.</param>
    /// <returns>
    /// True if the first temperature is less than or equal to the second. Otherwise, false.
    /// </returns>
    public static bool operator <=(Temperature t1, Temperature t2)
    {
        return t1._Kelvin <= t2._Kelvin;
    }

    /// <summary>
    /// Adds two instances of the temperature object.
    /// </summary>
    /// <param name="t1">The temperature on the left-hand side of the operator.
    /// </param>
    /// <param name="t2">The temperature on the right-hand side of the operator.
    /// </param>
    /// <returns>The sum of the two temperatures.</returns>
    public static Temperature operator +(Temperature t1, Temperature t2)
    {
        return new Temperature(t1._Kelvin + t2._Kelvin);
    }

    /// <summary>
    /// Subtracts one instance from another.
    /// </summary>
    /// <param name="t1">The temperature on the left-hand side of the operator.
    /// </param>
    /// <param name="t2">The temperature on the right-hand side of the operator.
    /// </param>
    /// <returns>The difference of the two temperatures.</returns>
    public static Temperature operator -(Temperature t1, Temperature t2)
    {
        return new Temperature(t1._Kelvin - t2._Kelvin);
    }

    /// <summary>
    /// Multiplies two instances of the temperature object.
    /// </summary>
    /// <param name="t1">The temperature on the left-hand side of the operator.
    /// </param>
    /// <param name="t2">The temperature on the right-hand side of the operator.
    /// </param>
    /// <returns>The product of the two temperatures.</returns>
    public static Temperature operator *(Temperature t1, Temperature t2)
    {
        return new Temperature(t1._Kelvin * t2._Kelvin);
    }

    /// <summary>
    /// Divides one instance of a temperature object by another.
    /// </summary>
    /// <param name="t1">The temperature on the left-hand side of the operator.
    /// </param>
    /// <param name="t2">The temperature on the right-hand side of the operator.
    /// </param>
    /// <returns>The quotient of the two temperature.</returns>
    public static Temperature operator /(Temperature t1, Temperature t2)
    {
        // TODO: Throw a divide-by-zero exception if needed.
        return new Temperature(t1._Kelvin / t2._Kelvin);
    }

    /// <summary>
    /// Finds the remainder when one instance of a temperature object is divided by another.
    /// </summary>
    /// <param name="t1">The temperature on the left-hand side of the operator.
    /// </param>
    /// <param name="t2">The temperature on the right-hand side of the operator.
    /// </param>
    /// <returns>The remainder after the quotient is found.</returns>
    public static Temperature operator %(Temperature t1, Temperature t2)
    {
        // TODO: Throw a divide-by-zero exception if needed.
        return new Temperature(t1._Kelvin % t2._Kelvin);
    }

    /// <summary>
    /// Converts a Kelvin temperature value to Celsius.
    /// </summary>
    /// <param name="kelvin">The Kelvin value to convert to Celsius.
    /// </param>
    /// <returns>The Kelvin value in Celsius.</returns>
    public static double KelvinToCelsius(double kelvin)
    {
        return kelvin - 273.15;
    }

    /// <summary>
    /// Converts a Celsius value to Kelvin.
    /// </summary>
    /// <param name="celsius">The Celsius value to convert to Kelvin.
    /// </param>
    /// <returns>The Celsius value in Kelvin.</returns>
    public static double CelsiusToKelvin(double celsius)
    {
        return celsius + 273.15;
    }

    /// <summary>
    /// Converts a Kelvin value to Fahrenheit.
    /// </summary>
    /// <param name="kelvin">The Kelvin value to convert to Fahrenheit.
    /// </param>
    /// <returns>The Kelvin value in Fahrenheit.</returns>
    public static double KelvinToFahrenheit(double kelvin)
    {
        return kelvin * 9 / 5 - 459.67;
    }

    /// <summary>
    /// Converts a Fahrenheit value to Kelvin.
    /// </summary>
    /// <param name="fahrenheit">The Fahrenheit value to convert to Kelvin.
    /// </param>
    /// <returns>The Fahrenheit value in Kelvin.</returns>
    public static double FahrenheitToKelvin(double fahrenheit)
    {
        return (fahrenheit + 459.67) * 5 / 9;
    }

    /// <summary>
    /// Converts a Fahrenheit value to Celsius.
    /// </summary>
    /// <param name="fahrenheit">The Fahrenheit value to convert to Celsius.
    /// </param>
    /// <returns>The Fahrenheit value in Celsius.</returns>
    public static double FahrenheitToCelsius(double fahrenheit)
    {
        return (fahrenheit - 32) * 5 / 9;
    }

    /// <summary>
    /// Converts a Celsius value to Fahrenheit.
    /// </summary>
    /// <param name="celsius">The Celsius value to convert to Fahrenheit.
    /// </param>
    /// <returns>The Celsius value in Fahrenheit.</returns>
    public static double CelsiusToFahrenheit(double celsius)
    {
        return celsius * 9 / 5 + 32;
    }
}

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here