在c#中将坐标存储为对象与两个双精度体的性能比较
本文关键字:双精度 两个 比较 性能比 性能 坐标 存储 对象 | 更新日期: 2023-09-27 18:02:51
我正在尝试优化一种算法,利用坐标列表。我们遵循领域驱动设计原则- Coordinate
目前被定义为一个单独的ValueObjects项目中的类,由主项目使用。Coordinate
类由两个double
s(纬度和经度)和构造函数中的一些验证组成,以确保在写入时有效的坐标。
使用Visual Studio的分析工具,我发现我的大量处理最终在get_Longitude和get_Latitude函数中结束。这可能是由于大量的呼叫。
是否值得将坐标存储为两个双精度体而不是一个包含两个双精度体作为属性的对象?或者这只会降低可读性而不会提高性能?
由于Coordinate
是一个值对象,因此它是不可变的。因此,使用两个readonly public
字段是完全可以接受的(但要读取其余字段)。
此外,使用结构体可以进一步提高计算性能(正如Jon Skeet在评论中指出的那样)。
从DDD的角度来看,这些都是非常好的实现细节。
此外:- 对于验证,我会在
Coordinate
定义中使用静态工厂方法对于计算,我会在Coordinate
定义中编写操作的闭包(但避免操作符重载,如果性能重要)这两种DDD模式可以在您的上下文中得到很好的证明。
在结构中拥有工厂方法(以及默认值的适当语义),使您能够删除构造函数中的验证逻辑,因为工厂方法本身将确保不变性(实际上,除了默认构造函数之外,您将没有任何公共构造函数)。
此外,假设您的Coordinate
形成一个可添加的组,该结构可以公开一个实例方法Coordinate Add(Coordinate other)
。在实现中,您不需要任何验证,但需要计算(基于对other
私有字段的访问)和初始化,因为您知道当前实例是有效的,因此它是参数。
注意,如果你在闭包操作上走得足够远,你将不需要任何公共字段或属性。
实际上,如果您关心OOP设计,而不是暴露任何内部信息(属性或字段,不会改变太多),您可以像下面这样暴露几个方法,而不会违反封装
public void Eval(Action<double, double> action)
{
if(null == action)
throw new ArgumentNullException("action");
action(_lat, _long);
}
public T Eval<T>(Func<double, double, T> function)
{
if (null == function)
throw new ArgumentNullException("function");
return function(_lat, _long);
}
此外,如果您需要这样的方法,但它们不属于您的通用语言,您可以将它们隐藏在基础设施 interface
的显式实现之后。