委托函数返回可为空值的问题

Problem with a delegate function returning a nullable value

我有以下代码:

private T? FromCache<T>(CacheKey key, Func<T?> retriever)
{
    if (cache.TryGetValue(key, out T res))
        return res;
    res = retriever();
    if (res is not null)
        cache.Set(key, res);
    return res;
}

public decimal? GetClosingExchangeRate(string sourceCurrencyCode, string targetCurrencyCode)
{
    return FromCache<decimal>(CacheKey.Closing(sourceCurrencyCode, targetCurrencyCode),
            // The following line results in this error:
            // Error CS0266  Cannot implicitly convert type 'decimal?' to 'decimal'.An explicit conversion exists (are you missing a cast?)
            () => GetExchangeRate(sourceCurrencyCode, targetCurrencyCode)?.ClosingRate
        );
}
public ExchangeRateDefinition? GetExchangeRate(string sourceCurrencyCode, string targetCurrencyCode)
{
    return GetExchangeRateQuery(sourceCurrencyCode, targetCurrencyCode).FirstOrDefault();
}
public class ExchangeRateDefinition
{
    [...]
    public decimal? ClosingRate { get; set; }
    [...]
}

在这种情况下,

我不明白这个错误:据我所知,传递给 FromCache 方法的委托有一个 return 类型的 T? 应该转换为 decimal? 即正是在我使用 returns 的委托时。然而,错误消息似乎表明编译器期望委托 return 是一个不可为 null 的小数。

为什么会出现此错误,我该如何解决?

我根据您的代码创建了一个可重现的示例:

internal class NullableExample
{
    private T? FromCache<T>(System.Func<T?> retriever)
    {
        return retriever();
    }

    public decimal? GetClosingExchangeRate()
    {
        return FromCache<decimal>(
                // The following line results in this error:
                // Error CS0266  Cannot implicitly convert type 'decimal?' to 'decimal'.An explicit conversion exists (are you missing a cast?)
                () => default(decimal?)
            );
    }
}

问题出在您对 FromCache<decimal> 的调用中:

您指定的类型参数是 decimal

GetExchangeRate(sourceCurrencyCode, targetCurrencyCode)?.ClosingRate

(我简化为default(decimal?))returns a decimal?.

你需要改变

FromCache<decimal>

FromCache<decimal?>

或者您可以省略类型参数并

return FromCache(
        // The following line results in this error:
        // Error CS0266  Cannot implicitly convert type 'decimal?' to 'decimal'.An explicit conversion exists (are you missing a cast?)
        () => default(decimal?)
    );

这样编译器就可以知道你在调用 FromCache<decimal?>.


潜在的问题是您使用的是 nullable reference type syntax but Decimal is a struct 所以当将 ` 传递给

private T? FromCache<T>(System.Func<T?> retriever)

编译器看到

private decimal FromCache<decimal>(System.Func<decimal> retriever)

而不是

private decimal? FromCache<decimal>(System.Func<decimal?> retriever)

如您所料。

您可以通过查看 Intellisense 中的内容来了解​​这一点(在 Visual Studio 中):

如果让 FromCache 使用 T 而不是 TT?(即摆脱可为 null 的引用类型语法),则会出现相同的问题:

internal class NullableExample
{
    private T FromCache<T>(System.Func<T> retriever)
    {
        return retriever();
    }

    public decimal? GetClosingExchangeRate()
    {
        return FromCache<decimal>(
                // The following line results in this error:
                // Error CS0266  Cannot implicitly convert type 'decimal?' to 'decimal'.An explicit conversion exists (are you missing a cast?)
                () => default(decimal?)
            );
    }
}