Требуется разъяснение значения Resharper NotNullAttribute

Рассмотрим следующий код:

    public static void Foo()
    {
        Bar(null);
    }

    public static void Bar([NotNull] string s)
    {
        if (s == null)
            throw new ArgumentNullException("s");
    }

Атрибут [NotNull] используется для Bar, чтобы сообщить вызывающим абонентам, что s не должно быть нулевым. Это работает нормально, и я получаю предупреждение, когда передаю null в Bar (Возможное присвоение 'null' объекту, отмеченному атрибутом 'NotNull').

Но на самом деле это не мешает мне передать значение null, поэтому Bar все равно должен проверять, является ли s значением null. Почему же я также получаю предупреждение о if (s == null) (Выражение всегда ложно)?

Насколько я могу судить, этот атрибут имеет неоднозначное значение; в зависимости от контекста это может означать две разные вещи:

  • для вызывающей стороны: не передавать пустой аргумент
  • для вызываемого: этот аргумент не нулевой

Я правильно использую этот атрибут или что-то упускаю?

Кстати, я использую Resharper 7 EAP, так что это может быть ошибка; однако я хочу убедиться, что мое использование правильно, прежде чем сообщить об этом...


РЕДАКТИРОВАТЬ: только что попробовал то же самое с R # 5.1 на работе; он показывает предупреждение на сайте вызова, но не в методе. Я сообщу об этом на Youtrack Jetbrain.


EDIT2: ошибка сообщается здесь


person Thomas Levesque    schedule 22.05.2012    source источник
comment
Что произойдет, если вы добавите второй вызывающий объект, который передает что-то отличное от null? Возможно, v7 выполняет более глубокий анализ источника значений и видит, что в этом случае единственный вызывающий Bar передает null...   -  person AakashM    schedule 22.05.2012
comment
кстати, насколько я знаю, семантика этого атрибута только является первым из ваших пунктов списка; это объявление метода внешнему миру.   -  person AakashM    schedule 22.05.2012
comment
@AakashM, хороший момент, но если бы он провел этот анализ, он должен сказать, что выражение всегда истинно, а не всегда ложно ... В любом случае, я попытался добавить вызов с ненулевым значением для s, и он все равно дает то же самое предупреждение.   -  person Thomas Levesque    schedule 22.05.2012
comment
О, упс, совершенно пропустил, что это было не так!   -  person AakashM    schedule 22.05.2012


Ответы (1)


Насколько я могу судить, вы используете его правильно, и ReSharper ошибается, говоря вам, что сравнение всегда false. Атрибут [NotNull] — это не более чем документация, и ваш код правильно проверяет входные значения. Это будет не первый раз, когда ReSharper делает неправильное или глупое предложение. Отличительной чертой JetBrains является то, что у них есть общедоступный трекер ошибок, где вы можете сообщить об этом и получить обратная связь напрямую от разработчиков.

Тем не менее (и простите меня, если вы знаете об этом), C# 4.0 Code Contracts делает это простым, предсказуемым и надежным:

Contract.RequiresAlways(s != null);
person Mahmoud Al-Qudsi    schedule 22.05.2012
comment
Судя по всему, это было исправлено в финальной версии R# 7. - person Thomas Levesque; 23.08.2012