1

オブジェクトの不変メソッドが特定の例外をスローするようにします。それは理にかなっていますか?C#で可能ですか?

たとえば、不変メソッドを持つクラス A と例外クラス E を含む次のコードがあります。今のところ、クラス E は A に参加していません...

class A {
    int x = 0, y = 1;

    [ContractInvariantMethod]
    private void YisGreaterThanX() {
        Contract.Invariant(x < y);
    }
}

class E : Exception {
}

そして、私が必要とするのは次のとおりです。Contract.Requires と同様に、Contract.Invariant (または、Exception 派生クラスを受け入れる属性コンストラクター) があると便利です。

class A {
    int x = 0, y = 1;

    [ContractInvariantMethod]
    private void YisGreaterThanX() {
        Contract.Invariant<E>(x < y);
    }
}

class E : Exception {
}

それは善意ですか?私のロジックが間違っている可能性がありますか?

4

1 に答える 1

0

Contract failures をキャッチすることは想定されておらず、明示的に指定された例外を伴うContract.Invariant のオーバーロードがないため、この答えは仮説に基づいていることを願っています。

したがって、すべての免責事項の後で、 ContractFailedイベント ハンドラーを配線することにより、次の行に沿って何かをハックできます。

Contract.ContractFailed += Contract_ContractFailed();

そしてハンドラーで、失敗をフィルタリングし、Invariant失敗を処理して例外を再スローします。

public static void Contract_ContractFailed(object sender,  ContractFailedEventArgs e)
{
    if (e.FailureKind == ContractFailureKind.Invariant)
    {
        e.SetHandled();
        throw new E(e.Message, e.OriginalException);
    }
}

定義で多くの情報を渡すことができないContract.Invariant場合、スローされた例外をパラメーター化する必要がある場合は、意図した例外をbool, string Contract.Invariantオーバーロードなどにエンコードするか、スレッド ローカル ストレージなどの外部グローバル状態を使用する必要があります。

これらはすべて臭い IMO です。最後の質問に答えるために、キャッチ可能な例外をスローすることはまったく良い考えではないと思います.コードは設計された状態の範囲外で呼び出されているため、どこかにバグ/検証がありません.

編集
その後、ハンドラーでの処理とスローContractFailedはまだ internal にラップされていることに気付きましたContractException。したがって、解凍する必要があります。

catch(Exception ex)
{
   var myException = ex.InnerException;
   // ... do something
}
于 2013-12-23T07:43:56.437 に答える