You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在领域层结构中用Int64替代DateTime/TimeSpan是否合理?

问题描述

我在.NET Framework的领域项目中定义了如下简单结构体:

public struct Candlestick
{
    public DateTime OpenTime;
    public DateTime CloseTime;
    public double Open;
    public double High;
    public double Low;
    public double Close;
    public double Volume;
}

业务逻辑中存在大量对Candlestick结构体列表执行时间搜索的方法,例如:

public static int IndexOfFirst(this IReadOnlyList<Candlestick> data, DateTime from)
{
    if (data == null)
        throw new ArgumentNullException(nameof(data));

    int count = data.Count;
    if (count == 0) return -1;

    int fromIdx = 0;
    while (data[fromIdx].OpenTime < from)
    {
        if (++fromIdx == count)
        {
            return -1;
        }
    }

    return fromIdx;
}

请问将Candlestick结构体中的时间变量改为long(Int64)类型,以提升逻辑层的操作性能是否合理?同时我计划在应用层(视图模型层的CandlestickVM)保留DateTime类型的时间变量。

为验证该想法,我在测试环境中进行了简单的性能测试:

DateTime a = new DateTime(2023, 01, 01);
DateTime b = new DateTime(2023, 02, 01);

TimeSpan incr = new TimeSpan(1);
DateTime now = a;
Stopwatch sw = Stopwatch.StartNew();
while (now < b)
{
    now += incr;
}
sw.Stop();
Console.WriteLine($"It took {sw.Elapsed} to run the Date & Time test.");

long incr2 = incr.Ticks;
long now2 = a.Ticks;
long bticks = b.Ticks;
sw.Restart();
while (now2 < bticks)
{
    now2 += incr2;
}
sw.Stop();
Console.WriteLine($"It took {sw.Elapsed} to run the long test.");

测试结果如下:

It took 00:00:04.8027716 to run the Date & Time test.
It took 00:00:00.9261338 to run the long test.
回答

这个改造方案完全合理,核心原因和注意事项如下:

1. 性能提升的核心逻辑

DateTime在.NET中本质是包装了long类型的Ticks值,但每次对DateTime做比较、加减操作时,会额外触发结构体的内部校验(比如日期范围合法性检查),而直接用long做数值比较是原生CPU操作,无额外开销——你的测试结果已经直观体现了这种差距,在大量循环的搜索场景中,这种性能提升会被进一步放大。

2. 分层设计的合理性

你计划的「领域层用long、应用层保留DateTime」完全符合关注点分离原则:

  • 领域层聚焦高效业务计算,不需要处理日期格式化、UI展示等逻辑,用long能最大化性能;
  • 应用层(视图模型)需要和UI交互,DateTime更便于绑定、格式化和用户理解,两者间的转换(new DateTime(ticks)或dateTime.Ticks)开销可以忽略不计。

3. 需注意的细节

  • 精度一致性:转换时统一使用Ticks作为单位,避免混用毫秒、秒等其他单位导致时间偏差;
  • 代码可读性:给long类型的时间字段加明确命名(比如OpenTimeTicks),避免后续维护时混淆数值含义;
  • 边界校验:如果业务涉及超出DateTime有效范围的时间,long能提供更大取值空间;若始终在DateTime范围内,转换时需校验避免生成无效实例。

4. 进一步优化建议

当前的IndexOfFirst是线性搜索,若数据量较大,建议改用二分查找——无论用DateTime还是long,二分查找时间复杂度为O(logN),远优于线性搜索的O(N),结合long的高性能比较,整体效率会有质的提升:

public static int IndexOfFirst(this IReadOnlyList<Candlestick> data, long fromTicks)
{
    if (data == null)
        throw new ArgumentNullException(nameof(data));

    int left = 0;
    int right = data.Count - 1;
    int result = -1;

    while (left <= right)
    {
        int mid = left + (right - left) / 2;
        if (data[mid].OpenTimeTicks >= fromTicks)
        {
            result = mid;
            right = mid - 1;
        }
        else
        {
            left = mid + 1;
        }
    }

    return result;
}

内容的提问来源于stack exchange,提问作者Timur Rozhok

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 22:09:24