Ваш анализ верен. Это не анализ, который выполняет компилятор, потому что компилятор выполняет анализ, который требуется спецификацией C #. Этот анализ выглядит следующим образом:
Если условие выражения condition?consequence:alternative
является константой времени компиляции true
, то альтернативная ветвь недоступна; если false
, то ветвь следствия недостижима; в противном случае обе ветви достижимы.
Условие в этом случае не является константой, поэтому и следствие, и альтернатива достижимы.
локальная переменная value
определенно присваивается только в том случае, если dict
не равно нулю, и, следовательно, value
- это , не определенно назначается при достижении следствия.
Но следствие требует, чтобы value
был определенно назначен
Так что это ошибка.
Компилятор не такой умный, как вы, но это точная реализация спецификации C #. (Обратите внимание, что я не набросал здесь дополнительные специальные правила для этой ситуации, которые включают в себя предикаты, такие как «определенно назначенные после истинного выражения» и т. Д. Для получения подробной информации см. Спецификацию C #.)
Кстати, компилятор C # 2.0 был слишком умным. Например, если бы у вас было условие типа 0 * x == 0
для некоторого int local x
, это вывело бы «это условие всегда истинно независимо от значения x
» и пометило бы альтернативную ветвь как недостижимую. Этот анализ был правильным в том смысле, что он соответствовал реальному миру, но он был неверным в том смысле, что спецификация C # ясно говорит, что вычет должен быть сделан только для констант времени компиляции, и в равной степени ясно, что выражения, включающие переменные не являются постоянными .
Помните, цель этой вещи - найти ошибки , и что более вероятно? Кто-то написал 0 * x == 0 ? foo : bar
, намереваясь, чтобы оно имело значение «всегда foo
», или что они написали ошибку случайно? Я исправил ошибку в компиляторе, и с тех пор он строго соответствует спецификации.
В вашем случае ошибки нет, но код слишком сложен для анализа компилятором, поэтому, вероятно, он слишком сложен, чтобы ожидать анализа от людей. Посмотрите, можете ли вы упростить это. Что я могу сделать, это:
public static V GetValueOrDefault<K, V>(
this Dictionary<K, V> d,
K key,
V defaultValue)
{
if (d != null && d.TryGetValue(key, out var value))
return value;
return defaultValue;
}
…
var result = dict.GetValueOrDefault(1, "Default");
Цель должна состоять в том, чтобы сделать сайт вызова читабельным; Я думаю, что мой сайт звонков значительно лучше читается, чем ваш.