.NET非空引用类型和方法的out参数

时间:2019-11-03 15:37:11

标签: c# .net .net-core c#-8.0

我添加csproj以在C#8中启用Null引用类型:

<Nullable>enable</Nullable>

此代码:

private static void Method()
{
    var dictionary = new Dictionary<string, string>();
    string value = string.Empty;

    dictionary.TryGetValue("Key", out value);
}

TryGetValue行带有警告:     警告CS8600:将空文字或可能的空值转换为非空类型。

我不明白为什么。 TryGetValue的签名是:

    public bool TryGetValue(string key, [MaybeNullWhen(false)] out string value);

该代码示例仅具有Non-Null引用。为什么会出现此错误?

2 个答案:

答案 0 :(得分:6)

如果在字典中未找到import math class Person: def __init__(self, name, age): self.name = name self.age = age def std_dev(persons): persons=Person mean = sum(persons)*1.0/len(persons) length = len(persons) mean = mean(persons) total_sum = 0 for i in range(length): total_sum += (persons[i]-mean)**2 square_root = total_sum*1.0/length return math.sqrt(square_root) ,则将"Key"的值分配给null变量。但是,您已将value声明为value,这意味着它不应包含string。因此,编译器会向您发出警告。

您最初将null分配给string.Empty的事实并不重要-这将始终被value覆盖(并且您应该得到另一个警告,指出这一点)。

您应将TryGetValue声明为value,以指示其值可能为string?

请注意,编译器非常聪明。如果您写:

null

然后编译器知道if (!dictionary.TryGetValue("Key", out string? value)) { value = string.Empty; } 不能为value,并且如果您随后尝试在其上调用方法,它也不会抱怨。

答案 1 :(得分:3)

canton7的答案是正确的(+1)。
这不是解释,而是一种解决方法:
您可以像这样向Dictionary<TVey, TValue>添加扩展方法:

public static bool TryGetValue<TKey, TValue>(this Dictionary<TKey, TValue> dictionary, TKey key, TValue @default, out TValue @value) where TKey : notnull
{
    var result = dictionary.TryGetValue(key, out var val);
    @value = result ? val : @default;
    return result;
}

然后您可以像这样使用它:

private static void Method()
{
    var dictionary = new Dictionary<string, string>();
    /// populate dictionary here...

    dictionary.TryGetValue("Key", string.Empty, out var value);
}

这应该使您能够将value保留为不可为空的字符串。