23. 事後条件
メソッドを出る瞬間に満たすべき条件
public static string Convert(string s)
{
Contract.Ensures(Contract.Result<string>() != null);
…
var t = Convert(s);
if (t != null) …
チェックしなくても非null保証あり
24. 不変条件
常に変わらない条件
public int X { get; set; }
public int Y { get; set; }
[ContractInvariantMethod]
void CheckInvariant()
{
Contract.Invariant(X + Y == 0);
}
25. 証明
証明(prove)
契約が満たされているか静的に検証
// 事後条件: null は返さないよ。
public static string GetString() { … }
// 事前条件: s は null を認めないよ。
public static string Convert(string s) { … }
var s = GetString();
var t = Convert(s);
nullは返ってこない
nullは渡らない
間にnullチェック不要
27. 契約はあくまで自己申告
全てのメソッドが正しく契約を表明しているとは限らない
// 契約に未対応。
public static string GetString() { … }
// 事前条件: s は null を認めないよ。
public static string Convert(string s) { … }
var s = GetString();
var t = Convert(s);
証明不能
var s = GetString();
Contract.Assume(s != null);
var t = Convert(s);
しょうがないから
「仮定」を入れる
動的なテストで確認
30. Requiresとかの中に掛けるメソッドは[Pure]でないと
Pure=副作用がない
[Pure]属性はあくまで自己申告なのだけども・・・
public int X { get; set; }
public int Y { get; set; }
[ContractInvariantMethod]
void CheckInvariant()
{
Contract.Invariant(Norm == 0);
}
[Pure]
public int Norm { get { return X + Y; } }