Click here to Skip to main content
Click here to Skip to main content
Technical Blog

A C# Temperature Struct

, 6 Jan 2012 CPOL
Rate this:
Please Sign up or sign in to vote.
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, and etc., 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;

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

    /// <span class="code-SummaryComment"><summary>
</span>    /// A scale of temperature on which water freezes
    /// at 0° and boils at 100° under standard conditions.
    /// <span class="code-SummaryComment"></summary>
</span>    Celsius,

    /// <span class="code-SummaryComment"><summary>
</span>    /// A scale of temperature on which water freezes at 32°
    /// and boils at 212° under standard conditions.
    /// <span class="code-SummaryComment"></summary>
</span>    Fahrenheit
}

/// <span class="code-SummaryComment"><summary>
</span>/// A temperature value.
/// <span class="code-SummaryComment"></summary>
</span>public struct Temperature : IFormattable, IComparable, 
       IComparable<Temperature>, IEquatable<Temperature>
{
    private double _Kelvin;

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

    /// <span class="code-SummaryComment"><summary>
</span>    /// Creates a new temperature with the specified value in the
    /// specified unit of measurement.
    /// <span class="code-SummaryComment"></summary>
</span>    /// <span class="code-SummaryComment"><param name="temperature">The value of the temperature.</param>
</span>    /// <span class="code-SummaryComment"><param name="unit">The unit of measurement that defines how
</span>    /// the <span class="code-SummaryComment"><paramref name="temperature"/> value is used.</param>
</span>    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.");
        }
    }

    /// <span class="code-SummaryComment"><summary>
</span>    /// Gets or sets the temperature value in Kelvin.
    /// <span class="code-SummaryComment"></summary>
</span>    public double Kelvin
    {
        get { return _Kelvin; }
        set { _Kelvin = value; }
    }

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

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

    /// <span class="code-SummaryComment"><summary>
</span>    /// Gets the temperature value in the specified unit of measurement.
    /// <span class="code-SummaryComment"></summary>
</span>    /// <span class="code-SummaryComment"><param name="unit">The unit of measurement
</span>    /// in which the temperature should be retrieved.<span class="code-SummaryComment"></param>
</span>    /// <span class="code-SummaryComment"><returns>The temperature value in the specified <paramref name="unit"/>.</returns>
</span>    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() + "'.");
        }
    }

    /// <span class="code-SummaryComment"><summary>
</span>    /// Returns a string representation of the temperature value.
    /// <span class="code-SummaryComment"></summary>
</span>    /// <span class="code-SummaryComment"><param name="format">
</span>    /// 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.
    /// <span class="code-SummaryComment"></param>
</span>    /// <span class="code-SummaryComment"><param name="provider">
</span>    /// An IFormatProvider reference that supplies culture-specific formatting
    /// services.
    /// <span class="code-SummaryComment"></param>
</span>    /// <span class="code-SummaryComment"><returns>A string representation of the temperature.</returns>
</span>    /// <span class="code-SummaryComment"><exception cref="FormatException">
</span>    /// The value of format is not null, the empty string (""), "G", "C", "F", or
    /// "K".
    /// <span class="code-SummaryComment"></exception>
</span>    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));
        }
    }

    /// <span class="code-SummaryComment"><summary>
</span>    /// Returns a string representation of the temperature value.
    /// <span class="code-SummaryComment"></summary>
</span>    /// <span class="code-SummaryComment"><param name="format">
</span>    /// 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.
    /// <span class="code-SummaryComment"></param>
</span>    /// <span class="code-SummaryComment"><returns>A string representation of the temperature.</returns>
</span>    /// <span class="code-SummaryComment"><exception cref="FormatException">
</span>    /// The value of format is not null, the empty string (""), "G", "C", "F", or
    /// "K".
    /// <span class="code-SummaryComment"></exception>
</span>    public string ToString(string format)
    {
        return ToString(format, null);
    }

    /// <span class="code-SummaryComment"><summary>
</span>    /// Returns a string representation of the temperature value.
    /// <span class="code-SummaryComment"></summary>
</span>    /// <span class="code-SummaryComment"><returns>A string representation of the temperature.</returns>
</span>    public override string ToString()
    {
        return ToString(null, null);
    }

    /// <span class="code-SummaryComment"><summary>
</span>    /// Returns a string representation of the temperature value.
    /// <span class="code-SummaryComment"></summary>
</span>    /// <span class="code-SummaryComment"><param name="unit">
</span>    /// The temperature unit as which the temperature value should be displayed.
    /// <span class="code-SummaryComment"></param>
</span>    /// <span class="code-SummaryComment"><param name="provider">
</span>    /// An IFormatProvider reference that supplies culture-specific formatting
    /// services.
    /// <span class="code-SummaryComment"></param>
</span>    /// <span class="code-SummaryComment"><returns>A string representation of the temperature.</returns>
</span>    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.");
        }
    }

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

    /// <span class="code-SummaryComment"><summary>
</span>    /// Compares this instance to a specified Temperature object and returns an indication
    /// of their relative values.
    /// <span class="code-SummaryComment"></summary>
</span>    /// <span class="code-SummaryComment"><param name="value">A Temperature object
</span>    ///    to compare to this instance.<span class="code-SummaryComment"></param>
</span>    /// <span class="code-SummaryComment"><returns>
</span>    /// 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.
    /// <span class="code-SummaryComment"></returns>
</span>    public int CompareTo(Temperature value)
    {
        return _Kelvin.CompareTo(value._Kelvin);
    }

    /// <span class="code-SummaryComment"><summary>
</span>    /// Compares this instance to a specified object and returns an indication of
    /// their relative values.
    /// <span class="code-SummaryComment"></summary>
</span>    /// <span class="code-SummaryComment"><param name="value">An object to compare, or null.</param>
</span>    /// <span class="code-SummaryComment"><returns>
</span>    /// 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.
    /// <span class="code-SummaryComment"></returns>
</span>    /// <span class="code-SummaryComment"><exception cref="ArgumentException">
</span>    /// The value is not a Temperature.
    /// <span class="code-SummaryComment"></exception>
</span>    public int CompareTo(object value)
    {
        if (value == null) return 1;
        if (!(value is Temperature)) throw new ArgumentException();
            return CompareTo((Temperature)value);
    }

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

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

        return Equals((Temperature)value);
    }

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

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

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

    /// <span class="code-SummaryComment"><summary>
</span>    /// Determines whether one temperature is considered greater than another.
    /// <span class="code-SummaryComment"></summary>
</span>    /// <span class="code-SummaryComment"><param name="t1">The first temperature to be compared.</param>
</span>    /// <span class="code-SummaryComment"><param name="t2">The second temperature to be compared.</param>
</span>    /// <span class="code-SummaryComment"><returns>True if the first temperature is greater than the second. Otherwise, false.</returns>
</span>    public static bool operator >

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

qenn
Engineer
United States United States
No Biography provided
Follow on   Twitter

Comments and Discussions

 
QuestionArithmetic operator overloads. Pinmembersupercat96-Jan-12 13:48 
AnswerRe: Arithmetic operator overloads. Pinmemberqenn12-Jan-12 10:01 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.141223.1 | Last Updated 6 Jan 2012
Article Copyright 2012 by qenn
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid