частью сигнатуры метода и их нельзя поместить в начало. Во время выполнения они
действуют идентично: проверяют переданное им условие и в случае его несоблюдения
генерируют исключение. Впрочем, есть еще и такой инструмент, как Code Contract
Checker (
CCCheck exe
), анализирующий производимый компилятором C# IL-код в
попытке статически удостовериться в отсутствии нарушений контракта. Эта утилита
пытается удостовериться, что все условия, переданные методу
Assert
, выполнены.
Если сделать это не получается, происходит переход к методу
Assume
.
Рассмотрим пример. Допустим, имеется следующее определение типа:
internal sealed class SomeType {
private static String s_name = "Jeffrey";
public static void ShowFirstLetter() {
Console.WriteLine(s_name[0]); // внимание: требования
// не подтверждены: index < this.Length
}
}
При построении этого кода с установленным флажком
Perform
Static
Contract
Checking
утилита
CCCheck exe
выводит предупреждение, приведенное в коммен-
тарии. Это сообщение уведомляет о том, что запрос первой буквы элемента
s_name
553
Контракты.кода
может закончиться неудачей и стать источником исключения, так как неизвестно,
всегда ли
s_name
ссылается на строку, состоящую хотя бы из одного символа.
Следовательно, в метод
ShowFirstLetter
нужно добавить утверждение:
public static void ShowFirstLetter() {
Contract.Assert(s_name.Length >= 1); // внимание: утверждение
// не подтверждено
Console.WriteLine(s_name[0]);
}
К сожалению, анализируя этот код, утилита
CCCheck exe
все равно не может про-
верить, ссылается ли элемент
s_name
на строку, содержащую хотя бы один символ.
В итоге мы снова получаем предупреждение. Иногда утилита не может проверить
утверждение из-за своих внутренних ограничений; вероятно, ее будущие версии
смогут осуществлять более полный анализ.
Чтобы обойти недостатки этой утилиты, перейдем от метода
Assert
к методу
Assume
. Зная наверняка, что никакой код не внесет изменений в элемент
s_name
,
мы можем отредактировать метод
ShowFirstLetter
следующим образом:
public static void ShowFirstLetter() {
Contract.Assume(s_name.Length >= 1); // Предостережений нет!
Console.WriteLine(s_name[0]);
}
В этой версии кода утилита
CCCheck exe
верит нам на слово и заключает, что
элемент
s_name
всегда ссылается на строку, содержащую хотя бы один символ.
В результате метод
ShowFirstLetter
проходит статическую проверку контракта
кода без предостерегающих сообщений.
Осталось рассмотреть инструмент Code Contract Reference Assembly Generator
(
CCRefGen exe
). Утилита
CCRewrite exe
ускоряет поиск ошибок, но произведенный
в процессе проверки контракта код увеличивает размер вашей сборки и отрица-
тельно сказывается на производительности. Исправить этот недостаток можно
при помощи утилиты
CCRefGen exe
, создающей отдельную
сборку со ссылкой на
контракт
. В Visual Studio она запускается автоматически, если выбрать в раскры-
вающемся списке
Contract
Reference
Assembly
вариант
Build
. Сборки с контрактами
обычно носят имя
ИмяСборки
Contracts dll
(например,
MSCorLib Contracts dll
) и со-
держат только метаданные и описывающий контракт IL-код. Опознать их можно
также по примененному к таблице метаданных с определением сборки атрибуту
System.Diagnostics.Contracts.ContractReferenceAssemblyAttribute
. Утилиты
CCRewrite exe
и
CCCheck exe
могут использовать сборки со ссылками на контракты
в качестве входных данных для анализа.
Ну и самый последний инструмент Code Contract Document Generator (
CCDocGen
exe
) добавляет информацию о контракте в XML-файл, создаваемый компилятором
C# при установке переключателя
/doc:file
. Этот XML-файл, дополненный утили-
той
CCDocGen exe
, после обработки инструментом Sandcastle выдает документацию
в стиле MSDN с информацией о контрактах.
Do'stlaringiz bilan baham: |