Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating a Temperature class which supports different units (Celsius, Fahrenheit, Kelvin)

I'm working on a class to help me to convert between units, and I need to ask about the best way to create this work.

This is my sample code about temperature:

        public class Temperature
{
    private double _Celsius = 0;
    public double Celsius
    {
        get { return _Celsius; }
        set
        {
            _Fahrenheit = (value * 9 / 5) + 32;
            _Kelvin = value + 273.15;
        }
    }
    private double _Fahrenheit = 0;
    public double Fahrenheit
    {
        get { return _Fahrenheit; }
        set
        {
            _Celsius = (value - 32) * 5/9;
            _Kelvin = _Celsius + 273.15;
        }
    }
    private double _Kelvin = 0;
    public double Kelvin
    {
        get { return _Kelvin; }
        set
        {
            _Celsius = value - 273.15;
            _Fahrenheit = (_Celsius * 9 / 5) + 32;
        }
    }
}

I hope to know if there is another good one for this class or not?

like image 859
JCompiler Avatar asked Feb 07 '23 09:02

JCompiler


2 Answers

Why do you have three fields _Celsius, _Fahrenheit, _Kelvin when just one (say, _Celsius) is enough:

  public class Temperature {
    private double _Celsius

    public double Celsius {
      get {
        return _Celsius;
      }
      set {
        // Simplest: no validation (e.g. -500 degree is an evident error)
        _Celsius = value;
      } 
    }

    public double Kelvin {
      get { 
        return Celsius + 273.15;
      }  
      set {
        Celsius = value - 273.15;
      } 
    }

    public double Fahrenheit {
      get { 
        return Celsius * 9 / 5 + 32;
      }  
      set {
        Celsius = (value - 32) * 5 / 9;
      } 
    }
  } 

Now let's think on what is the expected way of using your routine? E.g. I want to convert 100 Fahrenheit to Kelvin:

  double result = new Temperature() { Fahrenheit = 100.0 }.Kelvin;

a bit wordy and counter-intuitive, right? May be a better choice is to implement a bunch of static methods? And do not create any class at all?

  public static class Temperatures {
    public static double FahrenheitToCelsius(double value) {...} 

    public static double CelsiusToKelvin(double value) {...}

    public static double FahrenheitToKelvin(double value) {
      return CelsiusToKelvin(FahrenheitToCelsius(value)); 
    }
    ...
  } 

  ...

  double result = Temperatures.FahrenheitToKelvin(100.0); 
like image 139
Dmitry Bychenko Avatar answered Feb 12 '23 11:02

Dmitry Bychenko


A temperature is basically a type of "complex number." It can be measured in different units of measurement, but ultimately you should still be able to compare two different temperatures to determine if they're equal, or if one is "greater than" the other. You may also want to add two temperatures or subtract them.

I see this class behaving similarly to the .NET-provided TimeSpan class. Your Temperature class' implementation would choose a single unit of measurement to use privately - let's say Kelvin. The Temperature then provides "convenience" properties, which provide the temperature in any of your desired units of measurement (Farenheit or Celsius):

public class Temperature
{
    private double _kelvin = 0.0;
    public double Kelvin
    { 
        get { return _kelvin; }
        set { _kelvin = value; }
    }

    public double Fahrenheit 
    {
        get { return /* convert Kelvin to Fahrenheit */; }
        set { _kelvin = /* convert Fahrenheit to Kelvin */; }
    }


    public double Celsius
    {
        get { return /* convert Kelvin to Celsius */; }
        set { _kelvin = /* convert Celsius to Kelvin */; }
    }
}

Additionally - like the TimeSpan class - you'll want static methods which allow you to quickly and easily create an instance of your Temperature, using whatever "base measurement" unit you prefer at the time:

/* Also inside the Temperature class: */
public static Temperature FromKelvin(double kelvin)
{
    var temperature = new Temperature();
    temperature.Kelvin = kelvin;
    return temperature;
}

public static Temperature FromFahrenheit(double fahrenheit)
{
    var temperature = new Temperature();
    temperature.Fahrenheit = fahrenheit;
    return temperature;
}

public static Temperature FromCelsius(double celsius)
{
    var temperature = new Temperature();
    temperature.Celsius = celsius;
    return temperature;
}

Using this approach, you wind up with some nice clean usage syntax;

var myTemperatureInKelvin = Temperature.FromCelsius(100.0).Kelvin;

Finally - to get some real use out of such a class - you would want to implement comparison and arithmetic operators for equality, greater-than and less-than comparisons, addition, subtraction, etc. This allows you to very cleanly compare or add multiple temperatures together;

var resultInFahrenheit = (Temperature.FromCelsius(100.0) + Temperature.FromKelvin(200.0)).Fahrenheit;

Crazy! And useful!

like image 26
BTownTKD Avatar answered Feb 12 '23 10:02

BTownTKD