8

私はクラス ライブラリを作成しており、その一部は世界中の他のユーザーによって使用されています。Visual Studio 2010 を使い始めた今、通常の古いものではなく、コード コントラクトを使用することに切り替えるのがどれほど良い考えなのか疑問に思っています。スタイルifステートメント。

すなわち。これの代わりに:

if (fileName == null)
    throw new ArgumentNullException("fileName");

これを使って:

Contract.Requires(fileName != null);

私が質問している理由は、静的チェッカーを使用できないことを知っているためです。そのため、コンパイラーが検証できないいくつかの仮定について少し神経質になっています。これにより、静的チェッカーを使用している場合に、クラス ライブラリをダウンロードしてもコンパイルされない可能性があります。これは、問題を再現することさえできないという事実と相まって、修正するのが面倒になります。箱。

だから私はいくつかの質問があります:

  • アクセスできる場合、静的チェッカーはデフォルトでオンになっていますか? または、クラス ライブラリでオンにする必要がある設定がありますか (静的チェッカーがないため、しません)。
  • 私の恐れは不当ですか?上記のシナリオは実際の問題ですか?

どんなアドバイスでも大歓迎です。


編集:私が何を意味するのかを明確にしましょう。

クラスに次のメソッドがあるとします。

public void LogToFile(string fileName, string message)
{
    Contracts.Requires(fileName != null);
    // log to the file here
}

そして、私はこのコードを持っています:

public void Log(string message)
{
    var targetProvider = IoC.Resolve<IFileLogTargetProvider>();
    var fileName = targetProvider.GetTargetFileName();
    LogToFile(fileName, message);
}

さて、ここで IoC が起動し、いくつかの「ランダムな」クラスを解決して、ファイル名を提供します。このライブラリの場合、null 以外のファイル名を返さないクラスを取得する方法はありませんが、IoC 呼び出しの性質上、静的分析ではこれを確認できません。 、したがって、可能な値nullである可能性があると想定する場合があります。

したがって、静的分析では、LogToFileメソッドが引数で呼び出されるリスクがあり、nullビルドに失敗すると結論付ける場合があります。

コードに仮定を追加できることは理解しています。コンパイラは、fileNameそのメソッドから返される値が決してnullにならないことを前提としてそれを取るべきだと言っていますが、静的アナライザー(VS2010 Professional)がない場合は、上記のコードは私のためにコンパイルされるので、Ultimate を使用している誰かが見つけられるように、これを眠っているバグとして残しておくかもしれません。つまり、ここに問題がある可能性があるというコンパイル時の警告がないため、ライブラリをそのままリリースする可能性があります。

それで、これは本当のシナリオと問題ですか?

4

3 に答える 3

2

まず、静的チェッカーは実際には (私が理解しているように) アルティメット/アカデミック エディションでしか利用できません。そのため、組織内の全員がそれを使用しない限り、不変条件に違反している可能性がある場合に警告が表示されない可能性があります。

第二に、静的分析は印象的ですが、不変条件の違反につながる可能性のあるすべてのパスを常に見つけるとは限りません。ただし、ここでの朗報は、Requires コントラクトが実行時に保持されることです。コントラクトはIL 変換ステップで処理されるため、コンパイル時実行時の両方でチェックが行われます。if()このように、通常のチェックと同等 (ただし優れています)です。

コード コントラクトのコンパイルが実行するランタイムの書き換えについては、こちらで詳しく読むことができます。また、詳細なマニュアルもここで読むことができます。

編集:マニュアルから収集できることに基づいて、あなたが説明した状況が実際に可能であると思われます。ただし、これらはコンパイル エラーではなく警告であると考えていましたSystem.Diagnostics.CodeAnalysis.SuppressMessage()。静的ベリファイアを持つコードの消費者は、特定のケースを無視するようにマークすることもできますが、それらが多数ある場合は確かに不便です。私はあなたのシナリオの決定的なテストをまとめるため、今日しばらく時間を見つけようとします (現時点では静的検証ツールにアクセスできません)。

コード コントラクトにほぼ専念している優れたブログがここにあります (まだ見ていなければ) 興味のあるコンテンツがあるかもしれません。

于 2010-04-13T18:09:06.997 に答える
2

LogToFileとメソッドの両方Logがライブラリの一部であるLog場合、静的チェッカーをオンにすると、メソッドがコンパイルされない可能性があります。これはもちろん、静的チェッカーを使用してコードをコンパイルする他のユーザーにコードを提供する場合にも発生します。ただし、私の知る限り、クライアントの静的チェッカーは、出荷したアセンブリの内部を検証しません。アセンブリのパブリック API に対して独自のコードを静的にチェックします。したがって、DLL を出荷するだけであれば問題ありません。

もちろん、実際に静的チェッカーを有効にしているユーザーにとって非常に迷惑な API を持つライブラリを出荷するという変更があります。そのため、API の使いやすさをテストした場合は、契約定義を含むライブラリのみを出荷することをお勧めします。静的チェッカーの有無にかかわらず。

if (cond) throw ex既存の呼び出しをContracts.Requires(cond)、以前のリリースで既に出荷されているパブリック API 呼び出しの呼び出しに変更することについて警告してください。このRequiresメソッドは、通常スローするもの (a ) とは異なる例外 (RequiresViolationException私が正しく思い出せばa ) をスローすることに注意してくださいArgumentException。そのような状況では、Contract.Requiresオーバーロードを使用します。このようにして、API インターフェイスは変更されません。

于 2010-04-13T18:44:53.427 に答える
0

いいえ; 静的アナライザーがコンパイルの成功を妨げることはありません (クラッシュしない限り!)。

静的アナライザーは、証明されていない事前/事後条件について警告しますが、コンパイルを停止しません。

于 2010-04-14T00:03:22.557 に答える