Home > Back-end >  Why does IMemoryCache.GetOrCreateAsync return "TItem?" (nullable) instead of "TItem&q
Why does IMemoryCache.GetOrCreateAsync return "TItem?" (nullable) instead of "TItem&q

Time:01-13

The extension method GetOrCreateAsync for IMemoryCache:

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;
}

Why do they returns TItem? instead of just TItem? Assuming my factory method never returns null, is it safe to assume it would never be null and just ignore it with null-forgiving operator !?

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

CodePudding user response:

This github post has some important factors as to why they chose to make it a nullable return type. Here are a couple things to consider.

It is possible to cache a null value according to eerhardt.

In the post Stephen Toub states the following:

One of our overarching principles for nullable annotations in the core libraries it that they should never lie and say null isn't a possible result when in fact it is. This does lead to some cases where a method is annotated as returning a T? even if null is rare or relegated to a corner-case, e.g. Activator.CreateInstance returns T? because for example it can actually be null if you specify a Nullable as the type, but it means the nullability of the return value can be trusted: if it says it's non-nullable, then it won't ever be null, and callers don't need to guard against dereferencing null. The principles are outlined in https://github.com/dotnet/runtime/blob/main/docs/coding-guidelines/api-guidelines/nullability.md.

I hope this gives a clear idea why they chose to make it nullable. In your case if you are 100% sure that you won't cache any nullables you could in theory ignore the fact that it can return a null value. Although I don't recommend it in any case you program grows/ changes and requires this to be possible.

  • Related