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。我不确定在这里解决这个问题的正确方法。我需要确保当我进行比较值时,我实际上有一个真正的下界和上界值,并且下界值不高于上界值。

哦,我不能使用实际的 < 或 > 运算符,因为你不能将它们应用于类型“T”。


最后,我知道这可能是一个单独的问题,但它是高度相关的......如果有人知道为什么我在使用 Code Contracts 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

The problem with your method is that, when you call upperBound.CompareTo, you are assuming that the compiler knows that type T (which is the declared type of the upperBound parameter) implements the IComparable<T> interface (which declares the CompareTo method).

It is typically always the case (by convention) that an IComparable<T> interface would be implemented by the type T (if at all); however, the compiler does not know it unless you explicitly specify it through a type constraint.

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 回答
0

我将int用作示例。

合同int.CompareTo(int)不保证任何特定的返回值。知道 if a >= b, then a.CompareTo(b) >= 0,但由于这没有被表达为合同,静态检查器看到的唯一内容是“a.CompareTo(b) 返回一个 int”。“一个 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);
}

对于其他类型也是如此。

于 2012-02-29T18:01:41.837 回答