A C# Temperature Struct
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;
}
}