私はコード契約をもう少し詳しく理解しようとしています。私はtry/getパターンの不変条件をアサートしようとしていますが、true
を返し、out
オブジェクトがnullでない場合は、false
を返します。Contract.Ensuresのカスタムメソッド
public static bool TryParseFruit(string maybeFruit, out Fruit fruit)
{
Contract.Requires(maybeFruit != null);
Contract.Ensures((Contract.Result<bool>() && Contract.ValueAtReturn(out fruit) != null) ||
(!Contract.Result<bool>() && Contract.ValueAtReturn(out fruit) == null));
// Elided for brevity
if (ICanParseIt())
{
fruit = SomeNonNullValue;
return true;
}
else
{
fruit = null;
return false;
}
}
私はので、私はこのために私自身の方法を考慮したかったContract.Ensures
内の重複を好きではありません。
[Pure]
public static bool Implies(bool a, bool b)
{
return (a && b) || (!a && !b);
}
は、その後、私は
Contract.Ensures(Implies(Contract.Result<bool>(), Contract.ValueAtReturn(out fruit) != null);
にTryParseFruit
で私の不変を変えしかし、これは「証明されていない保証します」という警告を生成します。私がImplies
メソッドでインラインリファクタリングを実行すると、すべてが再びOKです。
誰かが私になぜこれが起こるのか説明できますか? Contract.ValueAtReturn
が何らかの方法で魔法のように使用されているため、結果を別の関数に渡して動作させることができないことを意味するので、私はそれを推測しています。
(更新#1)
私は、次のContract.Ensures
のすべてが同じことを表現することを考えて(つまり関数は、その後true
を返す場合fruit
がそうでなければ、非NULLであることをfruit
はnull
です)。私は一度にこれらのいずれかを使用していたことに注意してください:)
Contract.Ensures(Implies(Contract.Result<bool>(), Contract.ValueAtReturn(out fruit) != null));
Contract.Ensures(Contract.Result<bool>() == (Contract.ValueAtReturn(out fruit) != null));
Contract.Ensures(Contract.Result<bool>()^(Contract.ValueAtReturn(out fruit) == null));
ただし、以下のコードのクリーン・コンパイルに上記Contract.Ensures
鉛を全く。私はCode.Contractsがfruit.Name
はnull参照することはできないことを表現したい。
Fruit fruit;
while (!TryGetExample.TryParseFruit(ReadLine(), out fruit))
{
Console.WriteLine("Try again...");
}
Console.WriteLine(fruit.Name);
私は、上記の詳細な表現方法を使用すれば、完全にクリーンなコンパイルをコード契約で取得できます。私の質問はなぜです!
ありがとうございます。私は 'Contract.Ensures(Contract.Result)==(Contract.ValueAtReturn(out fruit)!= null));'を使ってみましたが、これは失敗します。私はすべての支店が "assert unproven"メッセージを出したので、Contract.Assertを使用してエラーケースを細くすることができませんでした。 –
編集された回答をご覧ください。 – phoog
答えをありがとう。私は自分のコードを単一のリターンポイント( 'return fruit!= null')に戻しました。これは、今や 'Contract.Ensures(Contract.Result()==(Contract.ValueAtReturn(out fruit)!= null));'スタイル契約が完全に完全にコンパイルされるように、定理証明者を少し助けるようです。 Code Contractsはプライムタイムの準備がまだ整っていないようです。私のメソッドの不変条件に簡単に注釈を付けて、それを「うまく動作させる」ことができるようにしたいと思いますが、少なくともこのバージョンでは少し野心的かもしれません。 –