Разве к этому моменту компилятору не должно быть очевидно, что myClass не допускает значения NULL?
Так оно и есть. Наведите указатель мыши на myClass
на нулевой проверке, и всплывающая подсказка из анализа stati c сообщит вам, что myClass
не является нулевым.
Итак, почему вы можете проверить его на нулевое значение? Потому что ты можешь. Это все еще ссылочный тип. Тот факт, что оно не будет нулевым, не аннотируется в типе.
Кроме того, обратите внимание, что он не сообщает вам, что исключение является недостижимым кодом. Почему это?
Ну, C# 8.0 анализ статических c ссылок, допускающих значение NULL, не надежен. Этого достаточно для большинства случаев. Однако время от времени появляются закономерности, которые они не распознают. Нужна помощь аннотаций и оператора, допускающего нуль (!). Что вы можете использовать, чтобы сообщить компилятору, когда вам будет лучше. Однако это оставляет место для лжи компилятору:
public MyClass GetMyClass()
{
return _obj!;
}
Точно так же вы можете проверить значение null в том, что, согласно компилятору stati c, не может иметь значение null. Потому что вам виднее:
public sealed class Service
{
private MyClass? _obj;
public MyClass GetMyClass()
{
return _obj!;
}
}
internal static class Program
{
private static void Main()
{
var service = new Service();
var myClass = service.GetMyClass();
// I am curious why this line compiles!
if (myClass == null)
{
throw new ArgumentNullException();
}
}
}
Конечно, я бы не рекомендовал на самом деле go вперед и l ie компилятору. Тем не менее, если вы получаете параметры от третьей стороны, рекомендуется выполнять нулевые проверки. Точно так же при использовании publi c API, когда вы не можете доверять реализации.
Я также напомню вам, что C# 8.0 обнуляемые ссылки - это функция, которая должна была постоянно разворачиваться в большие устаревшие кодовые базы. Это не было предназначено для того, чтобы помешать им компилироваться, когда вы включили это в одной части, а не в другой. На самом деле, насколько я могу судить, в худшем случае он выдаст предупреждения. Не компилировать нулевую проверку было бы go против этого.
Почему бы не выводить предупреждение о нулевой проверке?
Что ж, в этом случае Рослин уступает место разработчику. Если вы попытаетесь использовать myClass
внутри тела условного оператора и навести на него курсор, он сообщит вам, что он может иметь значение null. Что, конечно, было бы необходимо для ввода условного оператора в первую очередь.
Кроме того, удалите throw
и используйте myClass
после условного. Анализ stati c также скажет, что myClass
может иметь значение null после условия. Таким образом, Roslyn использует нулевую проверку как намек на то, что переменная действительно может иметь значение NULL.
Почему они решили использовать ее как подсказку вместо того, чтобы выдавать предупреждение? Этого я не знаю. Мне не удалось найти обсуждение на dotnet/csharplang
или dotnet/roslyn
на github.