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

С#: как реализовать и использовать атрибут NotNull и CanBeNull

Я хочу, чтобы программисты и я знали, что метод не хочет null, и если вы все равно отправляете ему null, результат будет не очень приятным.

В пространстве имен и CanBeNullAttribute находятся в Lokad Shared Libraries.

Но как это работает? Я посмотрел исходный код этих двух атрибутов, и он выглядит так:

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Parameter |
                AttributeTargets.Property | AttributeTargets.Delegate |
                AttributeTargets.Field, AllowMultiple = false, Inherited = true)]
[NoCodeCoverage]
public sealed class NotNullAttribute : Attribute
{
}

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Parameter |
                AttributeTargets.Property | AttributeTargets.Delegate |
                AttributeTargets.Field, AllowMultiple = false, Inherited = true)]
[NoCodeCoverage]
public sealed class CanBeNullAttribute : Attribute
{
}

Два пустых класса, наследующих от Attribute. Как они используются? Вам нужно искать xml-документацию и знать, что она есть? Потому что я попытался как сделать свою собственную копию атрибута, так и использовать версию Lokad, но когда я попытался отправить нуль прямо, я не получил сообщения. Ни от ReSharper, ни от VS. Который я как бы ожидал на самом деле. Но как они используются? Могу ли я каким-то образом заставить VS генерировать предупреждения для меня, если я попытаюсь отправить что-то, что там пусто? Или это просто используется в какой-то структуре тестирования? Или?

4b9b3361

Ответ 1

В среднесрочной перспективе "код контрактов" (в 4.0) будет лучшим ответом на это. Теперь они доступны (с академические или коммерческие лицензии), но будет более интегрирован в VS2010. Это может обеспечить как статический анализ, так и поддержку времени выполнения.

(изменить) пример:

Contract.RequiresAlways( x != null );

Простой, поскольку... механизм контрактов с кодом работает на уровне IL, поэтому он может анализировать это и вызывать предупреждения/ошибки из кода вызова во время сборки или во время выполнения. Для обратной совместимости, если у вас есть действующий код проверки, вы можете просто сказать, где заканчивается проверка работоспособности, и он сделает все остальное:

if ( x == null ) throw new ArgumentNullException("x");
Contract.EndContractBlock();

Ответ 2

Это можно сделать либо с помощью AOP, при котором Совет проверяет во время выполнения, является ли параметр метода пустым и допустимы ли null. См. PostSharp и Spring.NET для АОП.

Что касается ReSharper, см. Аннотированная структура:

Мы проанализировали значительную долю библиотеки классов .NET Framework, а также NUnit Framework и аннотировали ее через внешние XML файлы, используя набор пользовательских атрибутов из пространства имен JetBrains.Annotations, в частности:

  • StringFormatMethodAttribute (для методов, которые принимают форматированные строки как параметры)
  • InvokerParameterNameAttribute (для методов со строковыми литералами, которые должны соответствовать одному из параметров вызывающего абонента)
  • AssertionMethodAttribute (для методов утверждения)
  • AssertionConditionAttribute (для параметров параметров методов утверждения)
  • TerminatesProgramAttribute (для методов, которые завершают поток управления)
  • CanBeNullAttribute (для значений, которые могут быть пустыми)
  • NotNullAttribute (для значений, которые не могут быть нулевыми)

Ответ 3

Эти аннотации относятся к ReSharper и копируются из пространства имен JetBrains.Annotations. Рамки могут помещать их в собственное пространство имен, однако ReSharper НЕ подберет эти аннотации автоматически - вам нужно сказать ReSharper, чтобы использовать настраиваемое пространство имен в диалоговом окне параметров. После того как вы выбрали новое пространство имен, анализ ReSharper подберет атрибуты и даст вам основные моменты и предупреждения.

Ответ 4

Как указано Антоном Гоголевым, атрибуты могут быть созданы с использованием PostSharp (обратите внимание, что CodeContract использует вызовы статических методов внутри тела метода)

UPDATE Февраль 2013: новая версия 3.0 PostSharp (в настоящее время в бета-версии) будет поддерживать Проверка параметров, полей и свойств

1) Статья validate-parameters-using-attributes имеет реализацию

public class NotEmpty: ParameterAttribute

открытый класс NotNull: ParameterAttribute

[AttributeUsage (AttributeTargets.Parameter)]

public abstract class ParameterAttribute: Атрибут

{

public abstract void CheckParameter(ParameterInfo parameter, object value); 

}

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

2) В комментарии к статье есть ссылки на очень похожая реализация для NonNull/NonEmpty

[return: NonNull] public SomeObject SomeMethod ([NonNull] AnotherObject param1)

Исходный код находится в код Google Torch/DesignByContract

3) еще один более сложный пример описан в http://badecho.com/2011/11/validating-method-parameters-with-postsharp/