Удивительно, но я только смог найти один предыдущий вопрос о SO по этому вопросу, и я бы просто хотел получить сообщество «Голосую за доверие» (или нет!) По моему подходу.Debug.Assert vs Exceptions
Как я вижу это таким образом:
- использование
Debug.Assert
для государственных вещей, которые вы могли бы ожидать быть правдой. Это будет использоваться, когда мы полностью контролируем нашу среду, например, в методе проверяем некоторые предварительные и последующие условия. - Использование Исключения при возникновении особых обстоятельств. Работа с внешними ресурсами, то есть файлами, базами данных, сетями и т. Д., Не требует больших усилий. Но ...
Это выглядит немного мутным в следующем сценарии. Обратите внимание, что это КОНСТРУКТИВНЫЙ ПРИМЕР только для иллюстрации!
Скажем, у нас есть класс MyClass, который имеет общедоступное свойство MyMode и метод GetSomeValueForCurrentMode()
. Подумайте о MyClass как о том, что нужно отгрузить (релиз построен) в библиотеке для использования другими разработчиками.
Мы ожидаем, что MyMode будет обновлен внешними пользователями этого класса. Теперь GetSomeValueForCurrentMode()
имеет следующую логику:
switch(MyMode)
{
case Mode.ModeA:
return val1;
case Mode.ModeB:
return val2;
default:
//Uh-uh this should never happen
}
Что я клоню здесь является то, что пользователь MyClass оставил его в нерабочем состоянии. так что нам делать?
По умолчанию, должны ли мы Debug.Assert
или throw new InvalidOperationException
(или другие)?
Существует одна мантра, в которой говорится, что мы не должны доверять пользователям наших классов. Если мы выберем Debug.Assert и построим MyClass в качестве сборки релиза (таким образом удалив аргументы Debug), пользователь класса не получит полезную информацию, которую они оставили в недопустимом состоянии. Но это как-то противоречит другой мантре, в которой говорится только об исключении, когда происходят вещи, совершенно не зависящие от вашего контроля.
Я нахожусь в кругах с этим - один из тех дискуссий по программированию, которые, похоже, не имеют окончательного «правильного» ответа. Так что давайте поставим это на голосование!
Edit: я заметил этот ответ в родственной SO вопроса (Design by contract using assertions or exceptions?):
Правило большого пальца заключается в том, что вы должны использовать утверждение, когда вы пытаетесь поймать свои собственные ошибки и исключение при попытке поймать чужие ошибки. Другими словами, вы должны использовать исключения, чтобы проверить предварительные условия для общедоступных функций API и всякий раз, когда вы получаете какие-либо данные, которые являются внешними для вашей системы. Вы должны использовать утверждения для функций или данных, которые являются внутренними для вашей системы.
Для меня это имеет смысл и может сочетаться с техникой «Assert then throw», описанной ниже.
Мысли приветствуются!
Крис, выбрасывающий исключение «контракт сломанной» (который может только указывать на ошибку), не «быстро завершается», он «быстро выходит из строя»: сначала нужно выполнить разблокировку стека. Отмена прямо там, а затем, когда вы обнаружите нарушение контракта, будет реальным «неудачным быстрым». –
Y. Извините всех. Я удалил ссылку на «Fail Fast». Если вы хотите FailFast, вы можете использовать Environment.FailFast() в C#, а не исключать исключение. Но просто знайте, что ваши блоки finally не будут работать. – ChrisV
Рассмотрите возможность использования [fluentassertions] (http://fluentassertions.com/). Это помогает создавать читаемые контракты и в то же время выдает исключения, если контракты нарушаются. –