【问题标题】:Problem with a delegate function returning a nullable value委托函数返回可空值的问题
【发布时间】:2021-02-25 08:16:32
【问题描述】:

我有以下代码:

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 方法的委托的返回类型为T?,它应该转换为decimal?,这正是我使用的委托返回的时间。然而,错误消息似乎表明编译器正在期待一个返回非可空小数的委托。

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

【问题讨论】:

  • return FromCache&lt;decima?&gt; 也许.. 无论如何这远不是一个可重现的例子,我粘贴你的代码,其中大部分是错误
  • 您的问题似乎与 C# 版本 9 无关。我已经删除了那个标签,因为它不合适。如果您觉得您的问题是特定于 C# 9,您需要编辑帖子以说明原因。 FWIW,我同意之前的评论,即这个问题是不充分的,因为它缺乏适当的minimal reproducible example。另请参阅How to Ask,了解有关如何以清晰、可回答的方式提出问题的更多信息。

标签: c# delegates


【解决方案1】:

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

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&lt;decimal&gt;

您指定的类型参数是 decimal 但是

GetExchangeRate(sourceCurrencyCode, targetCurrencyCode)?.ClosingRate

(我将其简化为default(decimal?))返回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&lt;decimal?&gt;


根本问题是您使用的是nullable reference type 语法,但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 中)看到这一点:

如果您使FromCacheT 一起工作,而不是TT?(即去掉可为空的引用类型语法),则会出现同样的问题:

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

【讨论】:

  • 抱歉,我不明白:从缓存定义为private T? FromCache&lt;T&gt;? which should mean that FromCache`返回decimal?
  • 我已经编辑了我的答案 - 问题是您使用的是可为空的引用类型语法,但 Decimal 是一个结构。
猜你喜欢
  • 2010-12-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-29
  • 2022-06-29
相关资源
最近更新 更多