Dictionary.TryGetValue 和可能的 'null' 警告

Dictionary.TryGetValue and possible 'null' warning

在这种情况下,我似乎无法理解编译器的警告:

using System;
using System.Collections.Generic;

#nullable enable
                    
public class Program
{
    public static void Main()
    {
        Guid guid = Guid.NewGuid();
        
        Dictionary<Guid, string> d = new();
        
        bool found = d.TryGetValue(guid, out string? str);
        
        if (found is false)
        {
            return;
        }
        
        string s = str; // WARNING: possible null value
    }
}

毕竟,我正在做 found 检查和 return 如果没有值(例如,当 out str 值为 null 时)。另外,.TryGetValue 方法的 out 参数被注释为 [MaybeNullWhen(false)].

非常感谢您帮助我们找出我的预期错误之处并修复代码,谢谢。代码是 here.

基本上,当您使用局部变量时,编译器(或语言规范)不够“智能”,无法对来自 TryGetValue 的 return 值进行条件处理。

如果将 TryGetValue 调用内联到 if 条件中,则没问题:

if (!d.TryGetValue(guid, out string? str))
{
    return;
}
        
string s = str; // No warning

随着时间的推移,这可能会变得更加复杂,但是以 bullet-proof 的方式指定这类事情相对困难。

这不仅限于可为 null 的引用类型 - 还有其他情况,从人类的角度来看,逻辑代码是好的,但编译器会拒绝它。例如:

string text;
bool condition = DateTime.UtcNow.Hour == 5;
if (condition)
{
    text = "hello";
}
if (condition)
{
    Console.WriteLine(text); // Error: use of unassigned local variable
}

我们 知道如果我们进入第二个 if 语句体,我们也会进入第一个,所以 text 会有被分配了一个值,但编译器的规则并没有尝试足够聪明来发现它。