Это из-за разницы в компиляторе.
В этой скрипте https://dotnetfiddle.net/5GgGNS, вы можете увидеть ошибку, которая пропущена в моно-компиляторе.
Я думаю, что ошибкадопустимо в связи с тем, что эта строка
if (myDict?.TryGetValue("hello", out var value) == true)
не гарантирует инициализацию локальной переменной value
.
Если вы переписали бы ее в:
if (myDict?.TryGetValue("hello", out var value) == null)
он попытается получить доступ к value
.
Теперь значение null
или true
в вашем случае может быть возвращаемым значением функции, которое будет известно только во время выполнения.
Но, поскольку все переменные в основном всегда инициализируются , это просто функция компилятора.
С другой стороны, согласно спецификациям C # 5:
Локальная переменная, представленная объявлением локальной переменной, не инициализируется автоматически и поэтому не имеет значения по умолчанию.В целях проверки определенного присваивания локальная переменная, введенная объявлением локальной переменной, изначально считается неназначенной.Объявление локальной переменной может включать инициализатор локальной переменной, и в этом случае переменная считается определенно назначенной только после инициализирующего выражения (§5.3.3.4).
Но ваш код - C #6.
Итак, мой вывод заключается в том, что компиляторы интерпретируют это по-разному.Компилятор Microsoft учитывает оператор ?.
.Вы должны подать это как ошибку или найти хотя бы, возможно, даже на обеих сторонах.
Аргументация
Забавный факт, если вы используете этот код:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
class Program
{
static void Main()
{
//Your code goes here
Dictionary<string,int> myDict = null;
if (myDict?.TryGetValue("hello", out var value) == null)
{
Console.WriteLine("Hello" + value.ToString());
}
}
}
[использование https://www.jdoodle.com/compile-c-sharp-online, моно 5.10.1]
Вы увидите фактическую инициализацию для default(T)
на работе.Выход Hello0
.Тем не менее, это замечательно, потому что из-за ?
и того факта, что myDict
- это null
, TryGetValue
не следует вызывать и оставить value
"неинициализированным" .
Нулевые операторы имеют короткое замыкание.То есть, если одна операция в цепочке условных элементов или операций доступа к элементу возвращает ноль, остальная часть цепочки не выполняется.
source
Но ... , поскольку нет неинициализированных переменных;если он скомпилируется, компилятор удостоверится, что его поведение не определено.
Итак, поскольку value
инициализируется , во время выполнения остается вопрос, является ли этодопустимая ошибка компилятора во время сборки.Что касается времени выполнения кода, то оно есть (и именно поэтому ошибка была там, во-первых), но я думаю, что она остается серой областью.
Обратите внимание, что согласно это default(T)
не может быть переопределено, что фактически приведет к тому, что не произойдет сбой.
При выполнении этого небольшого теста:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
class Program
{
static void Main()
{
//Your code goes here
Dictionary<string,int> myDict = null;
if (myDict?.Bar(out var test) == null)
{
Console.WriteLine("does hit");
}
}
}
static class Foo
{
public static object Bar(this Dictionary<string,int> input, out int test)
{
test = 3;
Console.WriteLine("does not hit");
return 1;
}
}
[с использованием https://www.jdoodle.com/compile-c-sharp-online, моно 5.10.1]
Вывод становится:
does hit
И вы можете проверить правильное поведение во время выполнения оператора ?.
.