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

属性首次访问时缓存:Lazy<T>使用异常问题咨询

解决Lazy未缓存结果的问题

嘿,我懂你遇到的麻烦了——本来想用Lazy<T>实现“仅在属性被访问时才计算值,且之后缓存结果”的需求,但每次输出都得到不同的时间,说明你的Lazy<T>用法确实出了点问题。

问题根源

大概率是你在属性的getter里每次都创建了新的Lazy<DateTime>实例。举个反例,比如你可能写了这样的代码:

public DateTime ExpensiveValue
{
    get
    {
        // 错误:每次访问属性都新建一个Lazy,等于没缓存
        var lazy = new Lazy<DateTime>(() => DateTime.Now);
        return lazy.Value;
    }
}

这种写法下,每次访问ExpensiveValue都会生成一个全新的Lazy实例,自然每次都会重新计算时间,完全起不到缓存作用。

正确的实现方式

你需要把Lazy<T>实例作为类的私有只读字段,只初始化一次;然后属性的getter只返回这个实例的Value属性。这样第一次访问时触发计算,之后所有访问都会直接用缓存的结果。

代码示例:

public class MyDataClass
{
    // 私有Lazy字段:仅在类初始化时创建一次
    private readonly Lazy<DateTime> _cachedExpensiveValue = new Lazy<DateTime>(() =>
    {
        // 这里替换成你的实际高成本获取逻辑(比如数据库查询、远程调用等)
        Console.WriteLine("正在执行高成本计算...");
        return DateTime.Now;
    });

    // 公开属性:返回缓存的值
    public DateTime ExpensiveValue => _cachedExpensiveValue.Value;
}

测试验证

用下面的代码测试,你会发现只有第一次访问时会打印“正在执行高成本计算...”,两次输出的时间完全一致:

var dataObj = new MyDataClass();

// 第一次访问:触发计算
Console.WriteLine($"第一次访问结果:{dataObj.ExpensiveValue}");

// 等待1秒,模拟时间流逝
System.Threading.Thread.Sleep(1000);

// 第二次访问:直接返回缓存结果
Console.WriteLine($"第二次访问结果:{dataObj.ExpensiveValue}");

额外说明

  • 默认情况下,Lazy<T>是线程安全的(使用LazyThreadSafetyMode.ExecutionAndPublication模式),多线程环境下也只会计算一次值。
  • 如果你的场景不需要线程安全,可以在初始化Lazy<T>时指定LazyThreadSafetyMode.None,能稍微提升性能,但要注意线程安全问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 09:08:21