Подтвердить что ты не робот

Могу ли я преподавать ReSharper обычную проверку нуля?

ReSharper достаточно умен, чтобы знать, что a string.Format требует аргумент not-null format, поэтому он предупреждает меня об этом, когда я просто пишу

_message = string.Format(messageFormat, args);

где messageFormat действительно может быть нулевым. Как только я добавлю условие для этой переменной:

if (!string.IsNullOrEmpty(messageFormat))
{
    _message = string.Format(messageFormat, args);
}

предупреждение исчезает. К сожалению, это не происходит, когда я использую метод расширения:

if (messageFormat.IsNotNullOrEmpty())
{
    _message = string.Format(messageFormat, args); // possible 'null' assignment warning
}

Мой вопрос: есть ли способ научить ReSharper, что мой метод расширения имеет то же значение, что и !string.IsNullOrEmpty(messageFormat)?

Расширение определяется как:

public static bool IsNotNullOrEmpty([CanBeNull] this string value) => !IsNullOrEmpty(value);
4b9b3361

Ответ 1

Да, есть. Вам необходимо использовать аннотации ReSharper для руководства анализом ReSharper. Вы уже используете [CanBeNull], чтобы они уже были определены в вашем проекте.

Тот, который вас заинтересует, ContractAnnotationAttribute:

Контрактные аннотации позволяют определять ожидаемые выходные данные для заданных входов или, другими словами, определять зависимости между ссылочным типом и логическими аргументами функции и ее возвращаемого значения. Механизм контрактных аннотаций позволяет создавать API, которые можно было бы использовать проще и безопаснее.

Вот как вы его используете:

[ContractAnnotation("null => false")]
public static bool IsNotNullOrEmpty(this string value)
    => !string.IsNullOrEmpty(value);

Аргумент представляет собой карту возможных входов (null, notnull, true, false) для выходов (null, notnull, canbenull, true, false, halt):

Вот еще один пример:

[ContractAnnotation("foo: null => halt; bar: notnull => notnull")]
public string Frob(string foo, string bar)

означает, что декорированная функция никогда не вернется (или исключение), если вы передадите ее null в параметр foo и гарантирует, что она не вернет null, если вы передадите ненулевое значение до bar.

Документация описывает синтаксис более подробно.


Здесь что происходит без атрибута:

before

Предупреждение исчезает после его добавления:

после