Контрактные заявления и утверждения - PullRequest
1 голос
/ 28 ноября 2011

Это код из пользовательской Microsoft .NET реализации времени выполнения, и у меня есть следующие вопросы:

    public static string ToBase64String(byte[] inArray, int offset, int length)
    {
        if (inArray == null) throw new ArgumentNullException("inArray");
        if (offset < 0) throw new ArgumentOutOfRangeException("offset");
        if (length < 0) throw new ArgumentOutOfRangeException("length");
        if (offset + length > inArray.Length)
            throw new ArgumentException("offset + length > inArray.Length");

        // Fast return for the zero length case, note that this scenario is
        // absolutely valid.
        if (length == 0) return "";
        // ....
    }

Не должны ли операторы, которые проверяют предварительные условия (код контракта) для этого метода, фактически быть assert-like? Я имею в виду, откуда взялась идеология бросания исключений для кода нарушения контракта происходят от?

Я мог легко понять следующий код:

Contract.Requires(inArray != null);
Contract.Requires(offset >= 0);
// ...

Но выдает разные исключения ... Почему?

Невозможно правильно обработать такого рода исключения, потому что это просто указывает на логический недостаток, эта ошибка похожа на unchecked exception в Java, когда вы также даже не должны пытаться обработать это.

Теперь - я прав? Может быть, я не понимаю некоторые основополагающие принципы или склонен переусердствовать во всем?

Ответы [ 5 ]

2 голосов
/ 28 ноября 2011

Даже при использовании контрактов кода рекомендуется создавать конкретные исключения в коде выпуска, например:

Contract.Requires<ArgumentNullException>(...);

Первое: В своем коде выпуска / производства вы не хотите показывать пользователю окна подтверждения .

Альтернативой этому является , генерирующее ContractException , но это исключение не может быть "перехвачено", поскольку оно объявлено внутренним.

Единственная альтернатива, которая позволяет вызывающей стороне вашего кода корректно обрабатывать некоторые исключения (например, например, неверный ввод от пользователя), - генерировать исключения, которые он может перехватить .

Большим преимуществом Code Contracts является то, что вызывающая сторона может видеть исключения, которые вы будете выдавать (через автоматическую документацию sandcastle, * .Contracts.dll, плагины и инструменты, ...) и защищать себя от этих исключений. , Без кодовых контрактов ему пришлось бы полагаться на (вероятно, устаревшую) XML-документацию или даже вообще ничего.

1 голос
/ 28 ноября 2011

Я пробовал Contract.Requires и Exceptions.Я предпочитаю получить исключение, которое ясно говорит мне, что я неправильно использую метод.

Исключения следует использовать для исключительных вещей .Это тот случай, когда в метод передается неожиданный параметр.Они здесь, чтобы сообщить вам, что произошла неожиданная вещь.

0 голосов
/ 28 ноября 2011

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

Использование только Contract.Requires или тому подобного не дает такой большой информации.

0 голосов
/ 28 ноября 2011

Кодовые контракты поддерживают подход if-then-throw, чтобы упростить добавление контрактов в существующий код.

0 голосов
/ 28 ноября 2011

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

...