Очень важно отметить, что проверки на обнуляемость не только не являются пуленепробиваемыми, но хотя они предназначены для предотвращения звонящих от отправки null
ссылок, они ничего не делают для предотвращения это. Код все еще может компилироваться, который отправляет null
этому методу, и нет никакой проверки времени выполнения самих значений параметров.
Если вы уверены , что все вызывающие абоненты будут используя C# 8 контекст обнуляемости - например, это internal
метод - и вы действительно усердно работаете над разрешением всех предупреждений из анализа потока Статина c Рослина (например, вы настроили сервер сборки для обработки их как ошибок) тогда вы правы, что эти нулевые проверки являются избыточными.
Как отмечено в руководстве по миграции , однако, любой внешний код который не использует C# контекст обнуляемости, совершенно не заметит этого:
Новый синтаксис не обеспечивает проверку во время выполнения. Внешний код может обойти анализ потока компилятора.
Учитывая это, как правило, рекомендуется продолжать предоставлять защитные предложения и другие проверки обнуляемости в любых public
или protected
элементах.
На самом деле, если вы используете пакет Microsoft Code Analysis (который я бы порекомендовал), он предупредит вас использовать пункт охраны в этой конкретной ситуации. По общему признанию, это отчасти потому, что Code Analysis еще не поддерживает nullability . Но даже когда это произойдет, они все еще планируют сохранить это предупреждение на месте из-за вышеуказанных проблем.
Когда вы получите эти предупреждения из анализа кода, вы можете свернуть свой код в нулевая проверка, как вы сделали здесь. Но вы можете и выбросить исключение. На самом деле, вы могли бы бросить еще NullReferenceException
- хотя это определенно не рекомендуется. В таком случае вы должны вместо этого бросить ArgumentNullException
и передать имя параметра конструктору:
void Blah(SomeClass a) {
if (a == null) {
throw new ArgumentNullException(nameof(a));
}
…
}
Это гораздо предпочтительнее, чем бросать NullReferenceException
в источник, потому что это сообщает вызывающим абонентам, что они могут сделать, чтобы избежать этого сценария, явно назвав точный параметр (в данном случае), который был передан как null
. Это более полезно, чем просто получить NullReferenceException
- и , возможно * ссылку на ваш внутренний код - где произошло исключение.
Критически, это исключение не должно помочь you debug ваш код - это то, что Code Analysis делает для вас . Вместо этого он демонстрирует, что вы уже определили потенциальную разыменование нулевого значения, и вы составили для него в источнике .
Примечание: Эти защитные пункты могут добавить много шума в ваш код. Я предпочитаю создавать повторно используемую внутреннюю утилиту, которая обрабатывает это через одну строку. В качестве альтернативы, однострочный сокращенный код для приведенного выше кода:
void Blah(SomeClass a) {
_ = a?? throw new ArgumentNullException(nameof(a));
}
Это действительно окольный способ ответить на ваш первоначальный вопрос, а именно, как обнаружить наличие нулевых проверок, сделанных ненужными с помощью C # необнуляемые ссылочные типы.
Короткий ответ: вы не можете; на этом этапе анализ потоков Розелина c направлен на выявление возможности разыменования нулевых объектов, а не на обнаружение потенциально посторонних проверок.
Длинный ответ, хотя, как указано выше, заключается в том, что вы не должна ; до тех пор, пока Microsoft не добавит проверку во время выполнения или не разрешит контекст обнуляемости, эти пустые проверки продолжают давать значение.