Что делать при использовании Contract.Assert (true) и метод должен что-то возвращать? - PullRequest
5 голосов
/ 06 мая 2010

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

//pseudo-code
foreach (element in elementList) {
    if (element is whatever)
        return element;
    }
}

Теоретически, всегда есть один элемент, поэтому этот метод не должен создавать проблем. В любом случае я поставил утверждение в конце метода, чтобы быть уверенным:

//pseudo-code
foreach (element in elementList) {
    if (element is whatever)
        return element;
    }
}

Contract.Assert(false, "Invalid state!");

Проблема в том, что этот метод должен что-то возвращать, а компилятор не понимает, что утверждение нарушит выполнение программы. Прежде чем использовать контракты, в подобных ситуациях я использовал исключение, которое решило проблему. Как бы вы справились с этим с помощью Contract.Assert ()? Возврат null или default (element_type) после вызова Contract.Assert (), зная, что он никогда не будет вызван, и выключение компилятора? Или есть какой-нибудь более изящный способ сделать это?

Спасибо

Ответы [ 2 ]

2 голосов
/ 06 мая 2010

Вы могли бы пойти с

var result = null;
foreach (element in elementList) {
    if (element is whatever)
        result = element;
        break;
    }
}

Contract.Assert(result != null, "Invalid state!");
return result;

Вносит перерыв, но при возврате выглядит чище.

Даже чище будет

return elementList.Where( e => e is whatever).First();

Редактировать как @devoured указал, что вышеперечисленное попадет во весь список

очиститель без куда

return elementList.First( e => e is whatever);

конец редактирования

Это просто взрывается, если ничего не найдено.

Но если вы действительно хотите утвердить, это может быть

var results = elementList.Where( e => e is whatever);
Contract.Assert(results.Count() == 1, "Boo");
return results.First();

но это будет повторять весь список тоже.

1 голос
/ 03 августа 2010

Я думаю, вам лучше иметь Contract.Requires (т.е. предварительное условие), чем Contract.Assert здесь. Предварительным условием для вашего фрагмента является то, что elementList содержит хотя бы один элемент, в котором выполняется условие.

Вы должны быть откровенны в этом, а не полагаться на Assert(false), который требует от читателя понимания остальной функции и следит за управлением потоком данных для определения ситуаций, в которых достигается Assert(false).

Итак, я бы переписал как:

//precondition (checked only in debug builds)
Contract.Require(elementList.Where(e => e is whatever).Count > 0,"elementList requires at least one element meeting condition whatever");
//do work (throws in release builds, never reached in debug ones)
return elementList.First( e => e is whatever);
...