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

C#可空引用类型:Lookup函数如何同时支持可空与不可空值字典且不覆盖空检查?

问题原因

你遇到的编译报错是因为当前仅定义了接受值为可空类型的字典的重载,C# 9的可空引用类型泛型推导规则下,Dictionary<string, string>(值为不可空)无法自动匹配到Dictionary<TK, TV?>的参数签名,因此要求用户加!手动覆盖检查。

解决方案

无需修改LookupValue的原有签名,也不需要定义不同名的方法,只需要在同一个类中增加一个同名的泛型重载,专门处理值为不可空类型的字典即可,编译器会自动根据传入字典的可空性匹配对应重载,用户侧不需要任何额外语法处理。

完整可运行的代码如下:

class C1
{
    [Test]
    public void METHOD()
    {
        // 两个调用都可以正常编译,不需要加!
        var lookupValue1 = Lookup(new Dictionary<string, string?>(), "a");
        var lookupValue2 = Lookup(new Dictionary<string, string>(), "a");
    }

    // 重载1:处理值为不可空类型的字典
    public LookupValue<TV> Lookup<TK, TV>(Dictionary<TK, TV> d, TK key) 
        where TK : notnull
        where TV : notnull
    {
        if (d.TryGetValue(key, out var result))
        {
            return new LookupValue<TV>(result);
        }
        return new LookupValue<TV>(default);
    }

    // 重载2:处理值为可空类型的字典
    public LookupValue<TV> Lookup<TK, TV>(Dictionary<TK, TV?> d, TK key) 
        where TK : notnull
        where TV : notnull
    {
        if (d.TryGetValue(key, out var result))
        {
            return new LookupValue<TV>(result);
        }
        return new LookupValue<TV>(default);
    }

    // 原有签名完全保留
    public record LookupValue<T>(T? Value) where T : notnull;
}
补充说明

如果希望进一步减少重复代码,可以把两个重载的公共逻辑抽成私有方法,两个公共重载只做参数转发即可。
如果你不想用重载,也可以考虑升级到C# 11及以上版本,利用可空引用类型的泛型改进特性,用单个方法实现,但会提高框架依赖要求,综合来看C# 9下重载是兼容性和易用性最好的方案。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.10 19:27:01