【问题标题】:Creating a Temperature class which supports different units (Celsius, Fahrenheit, Kelvin)创建支持不同单位(摄氏度、华氏度、开尔文)的温度类
【发布时间】:2016-08-11 10:54:57
【问题描述】:

我正在做一个课程来帮助我在单位之间进行转换,我需要询问创建这项工作的最佳方法。

这是我关于温度的示例代码:

        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;
        }
    }
}

我希望知道这门课是否还有其他好的?

【问题讨论】:

  • “好人”是什么意思?
  • 在设置方法中,您没有设置正在设置的实际类型。例如,在摄氏设置器中,您设置了 _Farenheit 和 _Kelvin,但没有设置 _Celsius。
  • 您应该只存储一个值(即摄氏度)并直接在访问器中计算其他值。这可以防止对象的状态变得不一致。
  • 您的示例不是转换器类,而是包含物理单位(在本例中为温度)的类型。根据您的需要,您应该使用(无状态)转换类。

标签: c# .net oop temperature


【解决方案1】:

当只有一个(例如,_Celsius)就足够了时,为什么你有 三个 字段 _Celsius_Fahrenheit_Kelvin

  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;
      } 
    }
  } 

现在让我们考虑一下预期的日常使用方式是什么?例如。我想将100 Fahrenheit 转换为 Kelvin

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

有点罗嗦和违反直觉,对吧?可能更好的选择是实现一堆static methods?并且根本不创建任何类?

  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); 

【讨论】:

  • 我觉得它更像 TimeSpan 类。您可以使用静态方法轻松创建所需的 TimeSpan 实例,使用您的首选测量单位 (TimeSpan.FromMilliseconds(1000)),生成的 TimeSpan 实例提供属性,您可以通过这些属性轻松检索首选测量单位 (myTimeSpan.总秒数)。我可以看到一个对温度类有用的类似实现。 var myTemp = Temperature.FromCelsius(100.0); var farenheit = myTemp.Farenheit;
  • @BTownTKD:这是个好主意,我喜欢它,但在 Temperature 类的情况下,您必须实现 算术(如果我想添加,比如说,与初始温度相差 10 度,否则我必须找到室温和沸点之间的差异),比较(我想有可能写if (t1 >= t2) ...)和许多其他事情(比如,@987654332 @)
  • 确实如此。我已经提交了一个替代答案来解决这种方法。
  • @BTownTKD:我明白了;当密集工作与温度(不是偶尔从摄氏温度转换到开尔文温度)时,您的方法是更好的方法;当只是转换单位静态方法时,恕我直言,足够。 +1
  • 给你+1,先生!
【解决方案2】:

温度基本上是一种“复数”。它可以用不同的测量单位来测量,但最终你应该仍然能够比较两个不同的温度,以确定它们是否相等,或者一个是否“大于”另一个。您可能还想将两个温度相加或相减。

我看到这个类的行为类似于 .NET 提供的 TimeSpan 类。你的温度类的实现会选择一个单独的测量单位来私下使用——比如说开尔文。然后,Temperature 提供“便利”属性,以您想要的任何测量单位(华氏或摄氏度)提供温度:

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 */; }
    }
}

此外 - 就像 TimeSpan 类 - 您需要静态方法,以便使用您当时喜欢的任何“基本测量”单位快速轻松地创建温度实例:

/* 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;
}

使用这种方法,你会得到一些很好的干净的使用语法;

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

最后 - 要从这样的类中获得一些 真正的 用途 - 你会想要 implement comparison and arithmetic operators 进行相等、大于和小于比较、加法、减法等。这允许您可以非常清晰地比较或将多个温度相加;

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

疯了!而且很有用!

【讨论】:

    【解决方案3】:

    我猜您可能不想加载温度对象,您只想将一个数字转换为另一个数字。所以我会考虑将温度设为静态类,即

    public static Temperature
    

    所以你可以写一个类似的方法

    public static double GetKelvinFromCelsius(double celsius) {
         return (celsius + 273.15);
    }
    

    可以这样使用:

    double kelvinTemperature = Temperature.GetKelvinFromCelsius(400);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-02-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-02-05
      相关资源
      最近更新 更多