0

我运行这个开源库,巧妙地命名为Unit Class Library。它的目的,像许多其他人一样,是允许更智能地处理单位(四舍五入,转换等)。这里是图书馆的一个例子

Distance distance = new Distance(DistanceType.Inch, 3);

Area area = distance * distance;

显然,*运算符在 Distance 类中被重载,如下所示:

public static Area operator *(Distance d1, Distance d2)
{
    return new Area(d1, d2);
}

在尝试在实际应用程序中使用该库时,我需要使用这些类型做一些复杂的方程,并且目前必须将我的所有单位减少回任意双精度数来进行数学运算:

假设我们正在计算体积流量

(这只是一个例子。由于积分和导数,我的实际应用程序中的方程以距离 ^ 5th 和其他奇怪的单位结束。)

Volume v = new Volume(VolumeType.CubicMeters, 10); 
Time t = new Time(TimeType.Hours, 5);

double volumeAsDouble = v.CubicInches; 
double timeAsDouble = t.Seconds;

double flowRateAsDouble = volume / time;
VolumetricFlowRate flowRate = new VolumetricFlowRate(VolumetricFlowRateType.InchesCubedPerSecond, flowRateAsDouble);

这是一个令人不快的解决方案,因为它会导致不必要的转换。这引入了不必要的舍入误差。而且我知道我可以制作一个操作员来处理这个问题。

Tangent

如果您查看库的其余部分,您会发现从传入的值到不同单位的转换被延迟到需要它时。这确保了只要它与给定的单位相同,您将始终返回与输入相同的值。像这样:

Distance distance = new Distance(DistanceType.Inch, 0.0000000012345)

double inches = distance.Inches; //inches will equal 0.0000000012345

// other libraries will convert the input value as soon as the distance object is created.
// That would likely cause the number to be rounded. This library does not convert until a different unit is requested.

end Tangent

我希望能够做到这一点:

VolumetricFlowRate flowRate = volume / time;

无需编辑 Volume 类以包含新运算符。

我可以进入适当的位置并为每个新组合添加一个新的运算符,当它添加到库时应该返回 VolumetricFlowRate,但这很乏味并且违反了开放封闭原则。

有没有人提出一个解决方案的建议,该解决方案可以用每种新类型进行干净扩展,但又不违反开放封闭原则?

4

1 回答 1

-1

如果没有对变量单位的先验知识,就无法避免从一个单位转换到另一种单位。

在您的示例中,如果您知道所有距离都以米为单位,那么您可以将转换为每秒立方英寸的时间推迟到您真正需要此值的最后一刻。然后,“VolumetricFlowRate”类将处理每秒立方米到每秒立方英寸的转换。因此只需要一次转换。

但是,当并非所有距离都具有相同的单位时,这并不能解决额外转换的问题。

因此,为了尽量减少不必要的转换,您必须尽可能多地使用先验信息。

于 2015-03-27T21:34:29.520 回答