【发布时间】:2026-01-29 17:45:01
【问题描述】:
我正在尝试编写一个函数,它将字典的TryGet 转换为 C# 9.0 中的“查找”对象。到目前为止,我的(简化版)代码如下所示:
class C1
{
[Test]
public void METHOD()
{
var lookupValue1 = Lookup(new Dictionary<string, string?>(), "a");
var lookupValue2 = Lookup(new Dictionary<string, string>(), "a");
}
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);
}
else
{
return new LookupValue<TV>(default);
}
}
public record LookupValue<T>(T? Value) where T : notnull;
}
但是这段代码不会编译,具体来说就是这一行:var lookupValue2 = Lookup(new Dictionary<string, string>(), "a");
我知道我可以使用! 运算符覆盖空引用检查:var lookupValue2 = Lookup(new Dictionary<string, string>()!, "a"); 但这应该是一个公共 API,我不希望 API 的用户必须这样做。另外,我知道我可以在同一个类中创建两个名称不同的方法,或者在不同的类中创建相同名称的方法,但如果可能的话,我想避免这种情况。
有什么方法可以让这个Lookup 函数接受具有可空值类型的字典以及具有不可空值类型的字典并保留LookupValue 记录的签名?
【问题讨论】:
-
不幸的是,c# 一直在挖掘null hole even deeper。您真正需要的是一种描述optional type 并展开它的方法。
-
这种问题是由可空引用类型引入的。在 C#8 中它不会存在。
-
你不需要你的
LookupValue类型:它是多余的。为什么你认为你需要它? (而且你最终会让人们对 Linq 的ILookup感到困惑,这完全是另外一回事)。 -
您的
Lookup方法应该接受IReadOnlyDictionary,而不是Dictionary。 -
当
TV是一个结构时,return new LookupValue<TV>(default);这样做是一个非常糟糕的主意,因为没有迹象表明查找失败并且该值毫无意义。跨度>
标签: c# nullable-reference-types c#-9.0