Ненулевой тип ссылки .NET и выходной параметр метода - PullRequest
0 голосов
/ 03 ноября 2019

Я добавляю в csproj, чтобы включить пустой тип ссылки в C # 8:

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

Пример кода имеет только ненулевую ссылку. Почему он получил эту ошибку?

Ответы [ 2 ]

6 голосов
/ 03 ноября 2019

Если "Key" не найден в словаре, переменной value будет присвоено значение null. Однако вы объявили value как string, что означает, что он не должен содержать null. Поэтому компилятор выдает предупреждение.

Тот факт, что вы изначально присвоили string.Empty на value, не имеет значения - он всегда будет перезаписан на TryGetValue (и вы должны получить другоепредупреждение, которое говорит, что).

Вы должны объявить value как string?, чтобы указать, что его значение может быть null.

Обратите внимание, что компилятор довольно умен. Если вы напишите:

if (!dictionary.TryGetValue("Key", out string? value))
{
    value = string.Empty;
}

, то компилятор знает, что value не может быть null, и не будет жаловаться, если вы затем попытаетесь вызвать методы для него.

3 голосов
/ 03 ноября 2019

ответ кантона7 правильный (+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 как необнуляемую строку.

...