0

私は次の方法を持っています:

public static bool IsBetween<T>(this IComparable<T> value, T lowerBound, T upperBound)
    where T : IComparable<T>
{
    Contract.Requires<>(value != null);
    Contract.Requires<>(lowerBound != null);
    Contract.Requires<>(upperBound != null);
    Contract.Requires<>(upperBound.CompareTo(lowerBound) >= 0);

    return IsBetween(value, lowerBound, upperBound, InclusionOptions.None);
}

public static bool IsBetween<T>(this IComparable<T> value, T lowerBound, T upperBound,
     InclusionOptions options) where T : IComparable<T>
{
    Contract.Requires<>(value != null);
    Contract.Requires<>(lowerBound != null);
    Contract.Requires<>(upperBound != null);
    Contract.Requires<>(upperBound.CompareTo(lowerBound) >= 0); //Code Contracts Issue

    ...
}

ここでの問題は、私の最後の要件が気に入らないことです。それは述べていますCodeContracts: requires unproven: upperBound.CompareTo(lowerBound) >= 0。ここでこれを修正する適切な方法が本当にわかりません。比較値を実行するときに、実際に実際の lowerBound 値と upperBound 値があり、lowerBound 値が upperBound 値を超えていないことを確認する必要があります。

ああ、実際の < または > 演算子は使用できません。型 'T' には適用できないからです。


最後に、これは別の質問になる可能性があることは知っていますが、非常に関連しています...コード契約v1.4.50126.1を使用しているときにCA1062コード分析エラーが引き続き発生する理由を誰かが知っている場合は、修正する方法を教えてください:CA1062: Microsoft.Design : In externally visible method 'MyClass.IsBetween<T>(this IComparable<T>, T, T), validate parameter 'upperBound' before using it.

4

2 に答える 2

0

例として使用intします。

のコントラクトはint.CompareTo(int)、特定の戻り値を保証しません。if 、 thenはわかりますが、これはコントラクトとして表現されていないため、静的チェッカーが確認するのは「a.CompareTo(b) が int を返す」だけです。「int」が非負であることを証明することはできません。a >= ba.CompareTo(b) >= 0

次のようなものを追加できるはずです

Contract.Assert(a >= b);
Contract.Assume(a.CompareTo(b) >= 0);

関数を呼び出す場所で。これにより、静的チェッカーは最初にそれを証明しようとし、証明a >= bできない場合は通知してから、機能要件が満たされていることを信頼します。

に対してこの関数を頻繁に呼び出す場合は、この変更された固有のコントラクトintを使用してラッパー関数を作成することをお勧めします。int

public static bool IsBetween(this int value, int lowerBound, int upperBound)
{
    Contract.Requires<>(value != null);
    Contract.Requires<>(lowerBound != null);
    Contract.Requires<>(upperBound != null);
    Contract.Requires<>(upperBound >= lowerBound);
    Contract.Assume(upperBound.CompareTo(lowerBound) >= 0);
    return IsBetween<int>(value, lowerBound, upperBound);
}

他のタイプについても同様です。

于 2012-02-29T18:01:41.837 に答える
0

メソッドの問題は、 を呼び出すときに、型(パラメーターの宣言された型) がインターフェイス (メソッドを宣言する) を実装upperBound.CompareToしていることをコンパイラーが認識していると想定していることです。TupperBoundIComparable<T>CompareTo

通常、(慣例により)IComparable<T>型によってインターフェイスが実装される場合は常にそうTです (仮に実装されていたとしても)。ただし、型制約で明示的に指定しない限り、コンパイラはそれを認識しません。

public static bool IsBetween<T>(this T value, T lowerBound, T upperBound)
    where T : IComparable<T>
{
    Contract.Requires(value != null);
    Contract.Requires(lowerBound != null);
    Contract.Requires(upperBound != null);
    Contract.Requires(upperBound.CompareTo(lowerBound) >= 0);

    // ...
}
于 2012-02-25T16:29:00.343 に答える