550
Глава.20 .Исключения.и.управление.состоянием
его перехвата. Если же какой-нибудь из методов обработки становится источником
необработанного исключения, сначала вызываются все остальные обработчики,
а затем
генерируется исключение
ContractException
.
Если обработчики событий отсутствуют или ни один из них не вызывает методы
SetHandled
и
SetUnwind
и не становится источником необработанного исключе-
ния, нарушение контракта сопровождается заданной по умолчанию процедурой.
Если среда CLR загружена, приложение оповещается о нарушении контракта.
В случаях когда CLR запускает приложение в виде неинтерактивного оконного
терминала (сюда
относится, к примеру, Windows service application), вызывается
метод
Environment.FailFast
, мгновенно завершающий процесс. Если перед ком-
пиляцией
был установлен флажок
Assert
On
Contract
Failure
, появится диалоговое
окно, в котором с приложением можно будет связать отладчик. При сброшенном
флажке нарушение контракта сопровождается исключением
ContractException
.
Рассмотрим
пример класса, использующий контракты кода.
public sealed class Item { /* ... */ }
public sealed class ShoppingCart {
private List
- m_cart = new List
- ();
private Decimal m_totalCost = 0;
public ShoppingCart() {
}
public void AddItem(Item item) {
AddItemHelper(m_cart, item, ref m_totalCost);
}
private static void AddItemHelper(
List- m_cart, Item newItem, ref Decimal totalCost) {
// Предусловия:
Contract.Requires(newItem != null);
Contract.Requires(Contract.ForAll(m_cart, s => s != newItem));
// Постусловия:
Contract.Ensures(Contract.Exists(m_cart, s => s == newItem));
Contract.Ensures(totalCost >= Contract.OldValue(totalCost));
Contract.EnsuresOnThrow(
totalCost == Contract.OldValue(totalCost));
// Какие-то операции (способные сгенерировать IOException)
m_cart.Add(newItem);
totalCost += 1.00M;
}
// Инвариант
[ContractInvariantMethod]
private void ObjectInvariant() {
551
Контракты.кода
Contract.Invariant(m_totalCost >= 0);
}
}
В методе
AddItemHelper
определяется набор контрактов кода. Предусловие
указывает, что параметр
newItem
должен отличаться от
null
, а добавляемый
в список элемент не может дублировать уже имеющиеся.
Постусловие гласит,
что новый элемент должен присутствовать в списке, а общая цена покупок после
этой операции должна увеличиться. В постусловии также сказано, что если метод
AddItemHelper
по какой-то причине станет источником исключения
IOException
,
параметр
totalCost
должен
сохранить значение, которое он имел перед вызовом
метода. Закрытый метод
ObjectInvariant
гарантирует, что поле
m_totalCost
объ-
екта не будет содержать отрицательного значения.
Do'stlaringiz bilan baham: