11

Code Contracts を自分のコードに適用しようとしていますが、複雑な問題に遭遇しました。このコードは契約を満たしていませんが、私が本当に太っていない限りid、戻り点で値を持つ必要があることを簡単に分析できると期待しています

if (id == null)
    throw new InvalidOperationException(string.Format("{0} '{1}' does not yet have an identity", typeof(T).Name, entity));

return id.Value;

コード コントラクト エラー: 証明されていないものが必要です: HasValue

4

3 に答える 3

6

私はこの動作の真相を突き止めましたが、これはコード コントラクトのせいではありません。

生成されたアセンブリをILSpyで開いたところ、次のコードが生成されました。

public Guid Id
{
    get
    {
        Guid? guid = this.id;
        if (!guid.HasValue)
        {
            throw new InvalidOperationException();
        }
        guid = this.id;
        return guid.Value;
    }
}

インスタンス変数idはローカル変数にコピーされており、このローカル変数は条件ブロックの後で元の値にリセットされています。Code Contracts が契約違反エラーを表示する理由が明らかになりましたが、コードがこの形式で書き直された理由は依然として混乱していました。私はもう少し実験を行い、コード コントラクトをプロジェクトから完全に除外しました。これが標準的な C# コンパイラの動作であることが明らかになりましたが、なぜでしょうか?

秘密は、最初の質問から誤って省略した小さな詳細によるようです。idインスタンス変数は as として宣言されており、これがコンパイラに一時変数 readonlyを追加させる原因となっているようです。guid

不変性の保証を確実にするためにコンパイラがこれを行う必要があると感じる理由をまだ混乱していることを認めなければなりませんが、id掘り下げ続けます...

于 2011-07-27T16:05:07.307 に答える
1

フィールドをローカル値にコピーし、そのローカル値に関してステートメントを記述してみてください。呼び出しによってフィールド値が変更される可能性があるため、証明者はフィールドについて保守的である可能性があります。

于 2011-07-27T16:01:43.423 に答える
0

コントラクトの一部として if throw チェックが表示されません。代わりにこれを試してください:

if (id == null)    
  throw new InvalidOperationException(string.Format("{0} '{1}' does not yet have an identity", typeof(T).Name, entity));

Contract.EndContractBlock();

http://msdn.microsoft.com/en-us/library/system.diagnostics.contracts.contract.endcontractblock.aspx

于 2011-07-27T16:06:58.240 に答える