Когда проверять нулевые аргументы с включенными обнуляемыми ссылочными типами

Учитывая функцию в программе, использующей функцию обнуляемых ссылочных типов C# 8.0, я должен все еще выполнять нулевые проверки аргументов?

void Foo(string s, object o)
{
    if (s == null) throw new ArgumentNullException(nameof(s)); // Do I need these?
    if (o == null) throw new ArgumentNullException(nameof(o));
    ...
}

Ни один из кодов не является частью общедоступного API, поэтому я подозреваю, что эти проверки могут быть избыточными. Два параметра не помечены как обнуляемые, поэтому компилятор должен предупредить, если какой-либо вызывающий код может передавать значение NULL.

1 ответ

Решение

Учитывая функцию в программе, использующей функцию обнуляемых ссылочных типов C# 8.0, я должен все еще выполнять нулевые проверки аргументов?

Это зависит от того, насколько вы уверены во всех путях вашего API. Рассмотрим этот код:

public void Foo(string x)
{
    FooImpl(x);
}

private void FooImpl(string x)
{
    ...
}

Вот FooImpl не является частью общедоступного API, но все равно может получить нулевую ссылку, если Foo не проверяет свой параметр. (Действительно, это может быть полагаться на Foo выполнить проверку аргумента.)

Регистрация в FooImpl безусловно, не является избыточным в том смысле, что он выполняет проверки во время выполнения, в которых компилятор не может быть абсолютно уверен во время компиляции. Обнуляемые ссылочные типы улучшают общую безопасность и, что еще важнее, выразительность кода, но они не являются той же безопасностью типов, которую обеспечивает CLR (чтобы остановить обработку string ссылка как Type ссылка, например). Существуют различные способы, которыми компилятор может "ошибаться" в своем представлении о том, может ли конкретное выражение быть нулевым во время выполнения, и компилятор может быть переопределен с помощью ! тем не мение.

В более широком смысле: если ваши проверки не были избыточными до C# 8, они не избыточны после C# 8, потому что функция обнуляемого ссылочного типа не изменяет IL, сгенерированный для кода, кроме как с точки зрения атрибутов.

Так что, если ваш публичный API выполнял все соответствующие проверки параметров (Foo в приведенном выше примере) тогда проверка в коде уже была избыточной. Насколько вы уверены в этом? Если вы абсолютно уверены в себе, и влияние ошибки невелико, тогда обязательно - избавьтесь от проверки. Функция C# 8 может помочь вам обрести уверенность в этом, но вам все равно нужно быть осторожным, чтобы не стать слишком уверенным - в конце концов - приведенный выше код не даст никаких предупреждений.

Лично я не удаляю проверку параметров при обновлении Noda Time для C# 8.

Другие вопросы по тегам