单位转换程序

时间:2010-01-06 22:19:12

标签: c# wpf units-of-measurement

我正在为我的学期项目开发一个单位转换器。我需要一些关于类/接口/抽象类的结构的帮助。我想要一些可以由类继承的接口或抽象类(DegreesConverter,MassConverter,LenghtConverter)。就像interface IUnitConvert<Type>一样。我将为初学者处理角度(度,弧度,渐变),力(牛顿,帕斯卡)和数据(字节,千字节,兆字节,千兆字节,太字节)的单位。有什么建议吗?

3 个答案:

答案 0 :(得分:2)

首先想到的是System.TimeSpan,其中同一个类代表时间,您可以通过属性以不同的单位访问它。

您可以在内部以某个常量单位(可能是SI)存储该值,并将其转换为属性getter / setter:

Distance d = new Distance;
d.Meters = 5000;
var km = d.Kilometers; // km = 5;

或者您可以为每个单元创建类:

public sealed class DistanceUnit
{
    public DistanceUnit(string name, string symbol, double scale)
    {
        Name = name;
        Symbol = symbol;
        Scale = scale;
    }

    public string Name { get; private set; }
    public string Symbol { get; private set; }
    public double Scale { get; private set; }
}


public abstract class Distance
{
    protected Distance(double value)
    {
        this.Value = value;
    }

    protected Distance()
    {
    }

    public double Value { get; set; }

    public abstract DistanceUnit Unit { get; }

    public override string ToString()
    {
        return this.Value + " " + Unit.Symbol;
    }


    public static void Convert<TIn, TOut>(TIn original, out TOut result)
        where TIn : Distance, new()
        where TOut : Distance, new()
    {

        result = new TOut();

        var scale = result.Unit.Scale / original.Unit.Scale;

        result.Value = original.Value * scale;
    }

}

public sealed class Meter : Distance
{

    private static readonly DistanceUnit s_Unit = new DistanceUnit("Meter", "m", 1);

    public Meter(double value) : base(value)
    {
    }

    public Meter()
    {
    }

    public override DistanceUnit Unit
    {
        get { return s_Unit; }

    }
}

public sealed class Kilometer : Distance
{
    private static readonly DistanceUnit s_Unit = new DistanceUnit("Kilometer", "km", .001);

    public Kilometer()
    {
    }

    public Kilometer(double value)
        : base(value)
    {
    }

    public override DistanceUnit Unit
    {
        get { return s_Unit; }
    }
}

用于

Meter distanceHome = new Meter(10000);
Kilometer distanceInKMs;

Distance.Convert(distanceHome, out distanceInKMs);   //  distanceInKMs.Value = 10

答案 1 :(得分:1)

有很多不同的方法可以解决这个问题。这是使用代表的一种方式。

public class Converter
{
    public static double Convert(double original, Func<double, double> conversion)
    {
        return conversion(original);
    }
}

public class SizeConverter
{
    public static double MegabytesToBytes(double megabytes)
    {
        return megabytes * 1048576;
    }

    public static double KilobytesToBytes(double kilobytes)
    {
        return kilobytes * 1024;
    }
}

您可以这样使用:

        double result1 = Converter.Convert(2, SizeConverter.MegabytesToBytes);
        double result2 = Converter.Convert(2, SizeConverter.KilobytesToBytes);

如果您需要除双精度之外的其他类型,则需要重载Convert方法。

答案 2 :(得分:0)

想想你将如何使用它,并让它指导你。例如,您想要表示哪种度量单位?你的基本单位是什么?如何处理计量单位之间的转换?

我认为我们可以看到你需要某种方式来表示一个测量单位,例如英尺,米,升,弗隆,度,千克,磅,居里,欧姆等。这似乎是一个类或一系列类 - 可能以单位为基础,以英尺,米,升,弗隆为子类。然后我认为你需要一些方法来将一个单元与一个值相关联。这个单位/值必须提供一些方法来转换相同类型的度量单位(长度/距离,体积,温度,质量/重量),并且如果调用代码尝试一些可疑的东西,则要足够明亮以引发合理的异常(例如将27摄氏度转换为英里/小时)。创建单元/值实例的一些方便的方法将是方便的。单位/价值的东西不应该与特定类型或类别的单位联系在一起,但应该能够很好地处理你关心的任何单位。

Codewise我认为这样的事情会很棒:

UnitValue a, b, c;

a = new UnitValue(3 * 5280, Feet);
b = new UnitValue(180, Seconds);
c = (a / b).As(Miles / Hours);
cout << c;

应该有希望打印像

这样的东西
60 miles/hour

所以你可以看到将一个UnitValue除以另一个UnitValue应该产生一个带有复合单位的新UnitValue - 在这种情况下,a / b应该产生一个单位为英尺/秒(英尺/秒)的UnitValue,转换例程As然后将其转换为其他内容,在这种情况下为每小时英里数。

我希望这有助于激发你的一些想法。

分享并享受。