2

在某些类型的代码(例如模拟/游戏/优化)中,许多物理量/属性被存储、操作和暴露给对象(位置、速度、距离、面积、体积、时间、时差)。在这些类型的代码中,所有这些量通常由浮点数表示,即在 c# 中是双精度数。

这允许您将时间添加到距离、面积添加到体积、时间添加到时间以及位置添加到位置。

但你永远不想这样做。您只想将时间差添加到时间,添加到其他距离或位置的距离,并将区域与距离相乘。尽管如此,还是很容易出错,尤其是在处理其他人的代码时。

有很多选择可以减轻这种危险。您可以定义表示各种物理量的自定义类,然后以编程方式禁止某些类型的交互。或者您遵守严格的命名约定(例如 delay_timedifference)。在什么情况下(如果有的话),这两个选项中哪一个是最好的?如何实施第一个选项?如何为第二个选项命名?

4

3 回答 3

2

通常,使用第二个选项,但更多是为了方便。命名变得很明显你正在处理什么,即:命名属性AreaVolume,但即使那样,也存在单位问题。

您可以通过创建一整套自定义类(或不可变结构类型)来处理第一种情况来处理每种不同的组合,这可以很好地工作,但会使代码使用起来更加麻烦。框架中的DateTimestruct 就是一个很好的例子 - 在它的核心,它基本上只是一个长整数值,但它被包装到一个 struct 中以防止它在某个时刻被使用。

请注意,其他语言对此有选择 - 例如,F# 允许在语言级别处理单元,但在 C# 中不支持任何方式。

于 2012-06-29T15:31:40.220 回答
2

我认为将它们实现为结构而不是类是最有意义的,因为它们是值类型。您希望进行运算符重载以确保适当的运算符可用于相同类型的其他结构和适当的不同类型。您可能还想重载 ToString 函数以输出标量值,可能带有单位。

您还可以创建通用结构来创建其他结构的向量 - 这些可以是 2 维(x 和 y 属性)、3 维(x、y 和 z 属性)或 N 维(值数组)。这些结构还可以具有适当的运算符重载来执行向量计算。如果你做得正确,这将是一种与数据交互的非常自然的方式。

于 2012-06-29T15:34:17.947 回答
1

您描述的两个选项都是可行的,但它们都有缺点。第一个选项导致太多类(然后你需要定义很多关系),第二个可能容易出错。

更好的选择可能是创建一个自定义类,它既封装了浮点数,也封装了单位列表及其多重性。例如每秒 1 米可能变成 {n=1, types={length:1, time:-1}}。然后,您可以强制禁止任何数字进行比较、加法或减法,除非它们的单位相同。乘法和除法会将匹配类型的多重性加在一起。

例如。

1 m/s * 4 seconds = 4 meters
{n=1, types={length:1, time:-1}} * {n=4, types={time:1}} = {n=4, types={length:1,time:0}}
于 2012-06-29T15:35:06.883 回答