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

为何IMemoryCache.GetOrCreateAsync返回TItem?而非TItem?使用!是否安全?

关于IMemoryCache扩展方法GetOrCreateAsync的疑问

扩展方法定义

public static async Task<TItem?> GetOrCreateAsync<TItem>(this IMemoryCache cache, object key, Func<ICacheEntry, Task<TItem>> factory)
{
    if (!cache.TryGetValue(key, out object? result))
    {
        using ICacheEntry entry = cache.CreateEntry(key);

        result = await factory(entry).ConfigureAwait(false);
        entry.Value = result;
    }

    return (TItem?)result;
}

疑问1:为什么方法返回TItem?而非TItem?

原因主要有两点:

  • 缓存允许存储null值:IMemoryCache本身支持将null作为有效值存入缓存。如果之前有代码通过这个key存入了null,cache.TryGetValue会成功取出null,此时方法返回的就是null。
  • 兼容泛型的null场景:方法的泛型签名没有限制TItem不能为null(比如TItem是引用类型时,本身就允许为null)。返回TItem?是为了覆盖所有可能的null情况,符合C#可空引用类型的规范。

疑问2:若factory从不返回null,是否可以安全使用空原谅运算符!?

如果能同时满足以下两个条件,使用!是安全的:

  1. 你的factory方法绝对不会返回null,包括后续代码迭代中也不会出现返回null的情况。
  2. 该缓存key永远不会被存入null值——不管是自己的代码还是其他模块的代码,都不会往这个key写入null。

但要注意:一旦有代码往这个缓存key存入了null,或者factory意外返回null,使用!会直接触发NullReferenceException。如果无法完全控制缓存写入逻辑和factory的实现,这种写法就存在风险。

示例代码

public async Task<Foo> GetFooAsync()
    => (await cache.GetOrCreateAsync("Foo", async _ => new Foo()))!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 19:10:39