Представьте, что у вас есть метод, подобный следующему:
bool ContainsAnX(string s)
{
return s.Contains("X");
}
Теперь этот метод всегда завершится ошибкой, если вы передадите ему null
, поэтому вы хотите убедиться, что этого никогда не произойдет.Вот для чего Contract.Requires
.Он устанавливает предварительное условие для метода, которое должно быть истинным, чтобы метод работал правильно.В этом случае мы должны иметь:
bool ContainsAnX(string s)
{
Contract.Requires(s != null);
return s.Contains("X");
}
( Примечание : Requires
и Ensures
всегда должны быть в начале метода, поскольку они представляют собой информацию о методе какцелое. Assume
используется в самом коде, так как это информация об этой точке в коде.)
Теперь, в вашем коде, который вызывает метод "ContainsAnX", вы должны убедиться, что строкане является нулевымВаш метод может выглядеть следующим образом:
void DoSomething()
{
var example = "hello world";
if (ContainsAnX(example))
Console.WriteLine("The string contains an 'X'.");
else
Console.WriteLine("The string does not contain an 'X'.");
}
Это будет работать нормально, и статическая проверка может доказать, что example
не равен нулю.
Однако вы можете вызывать внешние библиотеки, которые не имеют никакой информации о значениях, которые они возвращают (т.е. они не используют кодовые контракты).Давайте изменим пример:
void DoSomething()
{
var example = OtherLibrary.FetchString();
if (ContainsAnX(example))
Console.WriteLine("The string contains an 'X'.");
else
Console.WriteLine("The string does not contain an 'X'.");
}
Если OtherLibrary
не использует кодовые контракты, статическая проверка будет жаловаться, что example
может быть нулевым.
Возможно, их документация длябиблиотека говорит, что метод никогда не вернет ноль (или должен никогда!).В этом случае мы знаем больше, чем статическая проверка, поэтому мы можем сказать Assume
, что переменная никогда не будет нулевой:
void DoSomething()
{
var example = OtherLibrary.FetchString();
Contract.Assume(example != null);
if (ContainsAnX(example))
Console.WriteLine("The string contains an 'X'.");
else
Console.WriteLine("The string does not contain an 'X'.");
}
Теперь это будет хорошосо статической проверкой.Если у вас включены контракты во время выполнения, Assume также будет проверяться во время выполнения.
Другой случай, когда вам может потребоваться Assume, - это когда ваши предварительные условия очень сложны, и статическая проверка испытывает трудности с их подтверждением.В этом случае вы можете слегка подтолкнуть его, чтобы помочь ему:)
С точки зрения поведения во время выполнения не будет большой разницы между использованием Assume и require.Однако результаты со статической проверкой будут сильно отличаться.Значение каждого также различно с точки зрения того, кто несет ответственность за ошибку в случае сбоя:
- Требуется означает, что код, вызывающий этот метод должен обеспечить выполнение условия.
- Предполагается, что этот метод делает предположение, которое всегда должно выполняться.