将坐标存储为对象与 C# 中的两个双打的性能

Performance of storing a coordinate as an object vs two doubles in C#

我正在尝试优化使用坐标列表的算法。我们遵循领域驱动设计原则 - Coordinate 目前在主项目使用的单独 ValueObjects 项目中定义为 class。 Coordinate class 由两个double(纬度和经度)和构造函数中的一些验证组成,以确保写入时有效坐标。

使用 Visual Studio 的分析工具,我发现我的大量处理都在 get_Longitude 和 get_Latitude 函数中结束。这可能只是因为调用的次数太多了。

是否值得将坐标存储为两个双精度而不是包含两个双精度作为属性的对象?或者这只会降低可读性而不会提高性能?

由于Coordinate是一个值对象,它是不可变的。因此,使用两个 readonly public 字段是完全可以接受的(但请阅读其余部分)。

此外,使用结构可以进一步提高计算性能(正如 Jon Skeet 在评论中指出的那样)。

从 DDD 的角度来看,这些是非常好的实现细节。

此外:

  • 为了验证,我会在 Coordinate 定义
  • 中使用静态 工厂方法
  • 为了计算,我会在 Coordinate 定义中编写 操作闭包 (但如果性能很重要,请避免运算符重载)

这两个 DDD 模式在您的上下文中可能会很好。

在结构中拥有工厂方法(以及默认值的正确语义),使您能够删除构造函数中的验证逻辑,因为不变量将由工厂方法本身确保(实际上您不会有任何 public 除了默认的构造函数)。

此外,假设您的 Coordinate 形成一个 additive group,该结构可以公开一个实例方法 Coordinate Add(Coordinate other)。 在实现中,您不需要任何验证,但需要计算(基于对 other 的私有字段的访问)和初始化,因为您知道当前实例是有效的,因此它是参数。

请注意,如果您在 关闭操作 方面走得足够远,您将不需要任何 public 字段或 属性.

事实上,如果您关心 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 的显式实现后面.