Я предполагаю, что к интерфейсу применяется контракт IHttpHandler.ProcessRequest , который требует этого контекста! = null. Контрактные интерфейсы наследуются их исполнителями, поэтому вам не нужно повторять Requires. Фактически, вам не разрешено добавлять дополнительные запросы Requires, так как вы ограничены требованиями, связанными с контрактом интерфейса.
Я думаю, что важно провести различие между указанием контрактного обязательства и просто выполнением нулевой проверки. Вы можете реализовать нулевую проверку и исключить исключение во время выполнения, чтобы сообщить разработчику, что они правильно используют ваш API. С другой стороны, выражение Контракта представляет собой действительно форму метаданных, которые могут быть интерпретированы контрактным переписывающим устройством (для представления исключений во время выполнения, которые были ранее реализованы вручную), а также статическим анализатором, который может использовать их для разбора о статической корректности вашего приложения.
Тем не менее, если вы работаете в среде, в которой вы активно используете Code Contracts и статический анализ, то, безусловно, предпочтительнее ставить утверждения в форме Контракта, чтобы воспользоваться статическим анализом. Даже если вы не используете статический анализ, вы все равно можете оставить дверь открытой для получения дополнительных преимуществ, используя контракты. Главное, на что следует обратить внимание, - настроить ли вы свои проекты для перезаписи, поскольку в противном случае контракты не приведут к исключениям времени выполнения, как вы могли бы ожидать.
Чтобы уточнить, что говорили комментаторы, разница между Assert, Assume и Requires:
- Контрактное выражение выражения преобразуется в утверждение контрактного переписывающего устройства, и статический анализатор пытается доказать выражение на основе имеющихся доказательств. Если это невозможно проверить, вы получите предупреждение о статическом анализе.
- Выражение Contract.Assume игнорируется контрактным переписывающим устройством (насколько мне известно), но интерпретируется статическим анализатором как новое доказательство, которое оно может принимать во внимание при его статическом анализе. Contract.Assume используется для «заполнения пробелов» в статическом анализе, либо там, где ему не хватает сложностей, чтобы делать необходимые выводы или когда они взаимодействуют с кодом, который не был украшен Контрактами, так что вы можете предположить, например , что конкретный вызов функции возвращает ненулевой результат.
- Contract.Requires - это условия, которые всегда должны быть истинными при вызове метода. Они могут быть ограничениями на параметры для метода (которые являются наиболее типичными), а также могут быть ограничениями на публично видимые состояния объекта (например, вы можете разрешить вызов метода только в том случае, если Initialized is True.) Эти типы Ограничения позволяют пользователям вашего класса либо проверять инициализацию при использовании объекта (и, предположительно, обрабатывать ошибку соответствующим образом, если это не так), либо создавать свои собственные ограничения и / или инварианты классов, чтобы уточнить, что Инициализация действительно произошла.