Хорошо, у меня есть еще один вопрос о Контрактах Кода. У меня есть контракт на методе интерфейса, который похож на это (другие методы, опущенные для ясности):
[ContractClassFor(typeof(IUnboundTagGroup))]
public abstract class ContractForIUnboundTagGroup : IUnboundTagGroup
{
public IUnboundTagGroup[] GetAllGroups()
{
Contract.Ensures(Contract.Result<IUnboundTagGroup[]>() != null);
Contract.Ensures(Contract.ForAll(Contract.Result<IUnboundTagGroup[]>(), g => g != null));
return null;
}
}
У меня есть код, использующий интерфейс, который похож на это:
public void AddRequested(IUnboundTagGroup group)
{
foreach (IUnboundTagGroup subGroup in group.GetAllGroups())
{
AddRequested(subGroup);
}
//Other stuff omitted
}
AddRequested
требует непустого входного параметра (он реализует интерфейс, который имеет, Требует контракта), и таким образом, я добираюсь, 'требует бездоказательный: группа! = пустая' ошибка на подгруппе, передаваемой в AddRequested
. Я использую синтаксис ForAll правильно? Раз так и решатель просто не понимает, там другой способ помочь решателю распознать контракт, или я должен просто использовать Принятие каждый раз, когда GetAllGroups () называют?
В Руководстве пользователя по контрактам на код говорится: «Статическая проверка контрактов еще не работает с квантователями ForAll или Exists». Пока это не произойдет, мне кажется, есть следующие варианты:
Contract.Assume (subGroup! = Null)
перед вызовом AddRequested ()
. AddRequested ()
. Может быть , если (подгруппа
== null) выбросить новое исключение InvalidOperationException ()
или if (subGroup! = null)
AddRequested (подгруппа)
. Вариант 1 особо не помогает. Вариант 2 является рискованным, поскольку он позволяет обойти контракт AddRequested ()
Requires, даже если IUnboundTagGroup.GetAllGroups ()
больше не гарантирует выполнение этого постусловия. Я бы выбрал вариант 3.