18
_foo
をnull
にすることはできませんが、次の単純なコードはコード契約の静的チェッカーによって「不変の不完全な」警告を生成します。この警告はreturn
の文内にUncalledMethod
です。returnステートメントに特定の新しいオブジェクトを作成するメソッドを使用すると、 "不変の不正解"
public class Node
{
public Node(string s1, string s2, string s3, string s4, object o,
string s5)
{
}
}
public class Bar
{
private readonly string _foo;
public Bar()
{
_foo = "foo";
}
private object UncalledMethod()
{
return new Node(string.Empty, string.Empty, string.Empty, string.Empty,
GetNode(), string.Empty);
}
private Node GetNode()
{
return null;
}
public string Foo
{
get
{
Contract.Ensures(Contract.Result<string>() != null);
return _foo;
}
}
[ContractInvariantMethod]
private void Invariants()
{
Contract.Invariant(_foo != null);
}
}
警告は単に無効であることを除けば、特定の状況でのみ発生します。以下のいずれかのを変更すると、警告が離れて行くようになります:のコンストラクタからS5に
return new Node(string.Empty, string.Empty, string.Empty, string.Empty, null,
string.Empty);
インライン
GetNode
はそうreturn文は次のようになりますNode
。- パラメータs1からs5のいずれかのタイプを、コンストラクタ
Node
からobject
に変更します。Node
のコンストラクタのパラメータの順序を変更するvar node = GetNode(); return new Node(string.Empty, string.Empty, string.Empty, string.Empty, node, string.Empty);
- :
は
GetNode
の結果のために一時的な変数を使用してください。- プロジェクト設定の[コード契約]設定ウィンドウで[前提条件を表示]オプションをオンにします。
静的チェッカーのバグですか?
マイセッティング:
マイ出力:
C:\{path}\Program.cs(20,9): message : CodeContracts: Suggested ensures: Contract.Ensures(this._foo != null);
C:\{path}\Program.cs(41,17): message : CodeContracts: Suggested ensures: Contract.Ensures(Contract.Result<System.String>() == this._foo);
C:\{path}\Program.cs(33,13): message : CodeContracts: Suggested ensures: Contract.Ensures(Contract.Result<ConsoleApplication3.Program+Node>() == null);
C:\{path}\Program.cs(27,13): message : CodeContracts: Suggested ensures: Contract.Ensures(Contract.Result<System.Object>() != null);
C:\{path}\Program.cs(55,13): message : CodeContracts: Suggested ensures: Contract.Ensures(Contract.ForAll(0, args.Length, __k__ => args[__k__] != 0));
CodeContracts: ConsoleApplication3: Validated: 92,3%
CodeContracts: ConsoleApplication3: Contract density: 1,81
CodeContracts: ConsoleApplication3: Total methods analyzed 8
CodeContracts: ConsoleApplication3: Methods with 0 warnings 7
CodeContracts: ConsoleApplication3: Total method analysis read from the cache 8
CodeContracts: ConsoleApplication3: Total time 2,522sec. 315ms/method
CodeContracts: ConsoleApplication3: Retained 0 preconditions after filtering
CodeContracts: ConsoleApplication3: Inferred 0 object invariants
CodeContracts: ConsoleApplication3: Retained 0 object invariants after filtering
CodeContracts: ConsoleApplication3: Detected 0 code fixes
CodeContracts: ConsoleApplication3: Proof obligations with a code fix: 0
C:\{path}\Program.cs(27,13): warning : CodeContracts: invariant unproven: _foo != null
C:\{path}\Program.cs(49,13): warning : + location related to previous warning
C:\windows\system32\ConsoleApplication3.exe(1,1): message : CodeContracts: Checked 13 assertions: 12 correct 1 unknown
CodeContracts: ConsoleApplication3:
CodeContracts: ConsoleApplication3: Background contract analysis done.
'Contract.Requires(_foo!= null)'を 'Bar'のコンストラクタに追加するとどうなりますか? –
@JohnWillemse:コンストラクタ内のフィールドにrequireを追加することはできません。さらに、コンストラクタが呼び出されたときに '_foo'がnullでなくてはならないことを意味するので、実際には意味をなさない。それ無理。 'Contract.Ensures(_foo!= null);'をctorに追加しても、警告は修正されません。 –
はい、申し訳ありません。私も同様の問題がありましたが、コンストラクタにはその場合に_fooを設定するパラメータがありました。私はここでそれを見落とした。 –