2012-02-25 9 views
0

を使用する場合、私は次のメソッドを持っている:コードコントラクト - 必須/証明されていない保証私はIComparableをやIComparableを<T>

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'に適用できないため、使用できません。


最後に、私が知っているこの別の質問することができますが、それは非常に関連しています...私はまだCA1062コード分析エラーが出る理由を誰かが知っている場合、私は、コードがv1.4.50126.1をコントラクト使用しているときそれを修正するために何をすべきかを教えてください:CA1062: Microsoft.Design : In externally visible method 'MyClass.IsBetween<T>(this IComparable<T>, T, T), validate parameter 'upperBound' before using it.

+0

私は 'Contract'を使用していませんが、警告はメソッド定義自体ではなく、あなたのメソッドのコードに関係しませんか?あなたは、条件に違反しているあなたのアプリケーションで何か電話をしていますか? – Douglas

+0

Nope。これは私のユーティリティクラスです。そのクラスのコードはこのメンバを呼び出しません。それは100%単離されている。 –

+0

CA1062分析を削除することをおすすめします。現時点ではコード契約と互換性がなく、潜在的な問題がある場合は、コード契約により警告されます。 – porges

答えて

0

あなたの方法の問題点は、upperBound.CompareToを呼び出すとき、あなたはコンパイラが実装(upperBoundパラメータの宣言された型がある)というタイプTを知っていることを想定しているということですIComparable<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); 

    // ... 
} 
+0

ああ、申し訳ありません...私の急いで、私は型の制約があることを忘れてしまったことを忘れていました...しかし、問題がある行とは何の関係もないことは分かりません。 –

+0

型制約を追加しないと、行はコンパイルに失敗します。 – Douglas

+0

ダグラス:私はその行を持っています(したがってそれはコンパイルされます)。私のコードをコピーして、Stackoverflowでうまく見えるように書式設定するという私の急いで、制約線を削除しました。私は一般的な制約があります。私は正確に私の方法を反映するために私の質問を更新しました。 –

0

例としてintを使用します。

int.CompareTo(int)の契約では、特定の戻り値が保証されません。 a >= bの場合はa.CompareTo(b) >= 0となりますが、これは契約書では表現されていないため、静的チェッカーで表示されるのは「a.CompareTo(b)int」です。 「整数」は非負であることは証明できません。

あなたは、あなたの関数を呼び出す場所で

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); 
} 

と同様。

関連する問題