可扩展的单元类智能操作员解决方案

时间:2015-03-27 11:13:38

标签: c# operator-overloading open-closed-principle unit-class-library

我运行这个开源库,巧妙地命名为Unit Class Library。它的目的是like many others允许更加智能地处理单位(舍入,转换等)。这是图书馆工作的一个例子

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

在尝试在真实应用程序中使用库时,我需要使用这些类型来执行一些复杂的方程式,并且我当前必须将所有单位减少到任意双精度才能进行数学运算:< / p>

我们假装正在计算Volumetric Flow Rate

(这只是一个例子。我的实际应用中的方程最终得到了距离^ 5和其他奇怪的单位,这是由于积分和导数。)

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,但这很乏味并打破了开放的封闭原则。

是否有人建议使用每种新类型彻底扩展的解决方案,但不打破开放封闭原则?

1 个答案:

答案 0 :(得分:-1)

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

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

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

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