CodeContracts:假设/断言的重用?(CodeContracts: Reuse of as

2019-10-17 01:38发布

我已为这对CodeContracts论坛在MSDN,但显然没有人知道或困扰寻找到这个问题。

我试图减少重复性的断言,并使其更具重用性但不幸的是,这并不工作,你能解释一下为什么?

[ContractVerification(false)]
public static class Assert
{
    [Conditional("DEBUG")]
    public static void GreaterThan<T>(T value, T lowerBound) where T : IComparable<T>
    {
        Contract.Ensures(value.CompareTo(lowerBound) > 0);
    }

    [Conditional("DEBUG")]
    public static void GreaterThanOrEqual<T>(T value, T lowerBound) where T : IComparable<T>
    {
        Contract.Ensures(value.CompareTo(lowerBound) >= 0);
    }

    [Conditional("DEBUG")]
    public static void LessThan<T>(T value, T upperBound) where T : IComparable<T>
    {
        Contract.Ensures(value.CompareTo(upperBound) < 0);
    }

    [Conditional("DEBUG")]
    public static void LessThanOrEqual<T>(T value, T upperBound) where T : IComparable<T>
    {
        Contract.Ensures(value.CompareTo(upperBound) <= 0);
    }

    [Conditional("DEBUG")]
    public static void NotNull(object value)
    {
        Contract.Ensures(value != null);
    }

    [Conditional("DEBUG")]
    public static void NotNullOrEmpty(string value)
    {
        Contract.Ensures(!string.IsNullOrEmpty(value));
    }

    [Conditional("DEBUG")]
    public static void True(bool value)
    {
        Contract.Ensures(value);
    }

    [Conditional("DEBUG")]
    public static void False(bool value)
    {
        Contract.Ensures(!value);
    }

    [Conditional("DEBUG")]
    public static void InRange<T>(T value, T lowerBound, T upperBound, ExclusionMode exclusionMode = ExclusionMode.None) where T : IComparable<T>
    {
        Contract.Ensures(((exclusionMode | ExclusionMode.LowerBound) == ExclusionMode.LowerBound ? value.CompareTo(lowerBound) > 0 : value.CompareTo(lowerBound) >= 0) && ((exclusionMode | ExclusionMode.UpperBound) == ExclusionMode.UpperBound ? value.CompareTo(upperBound) < 0 : value.CompareTo(upperBound) <= 0));
    }
}

我把它改成下面的,它似乎工作,但显然通用版本是更可取。

[ContractVerification(false)]
public static class Assert
{
    [Conditional("DEBUG")]
    public static void GreaterThan(int value, int lowerBound)
    {
        Contract.Ensures(value > lowerBound);
    }

    [Conditional("DEBUG")]
    public static void GreaterThanOrEqual(int value, int lowerBound)
    {
        Contract.Ensures(value >= lowerBound);
    }

    [Conditional("DEBUG")]
    public static void LessThan(int value, int upperBound)
    {
        Contract.Ensures(value < upperBound);
    }

    [Conditional("DEBUG")]
    public static void LessThanOrEqual(int value, int upperBound)
    {
        Contract.Ensures(value <= upperBound);
    }

    [Conditional("DEBUG")]
    public static void NotNull(object value)
    {
        Contract.Ensures(value != null);
    }

    [Conditional("DEBUG")]
    public static void NotNullOrEmpty(string value)
    {
        Contract.Ensures(!string.IsNullOrEmpty(value));
    }

    [Conditional("DEBUG")]
    public static void True(bool value)
    {
        Contract.Ensures(value);
    }

    [Conditional("DEBUG")]
    public static void False(bool value)
    {
        Contract.Ensures(!value);
    }

    [Conditional("DEBUG")]
    public static void InRange(int value, int lowerBound, int upperBound, ExclusionMode exclusionMode = ExclusionMode.None)
    {
        Contract.Ensures(((exclusionMode | ExclusionMode.LowerBound) == ExclusionMode.LowerBound ? value > lowerBound : value >= lowerBound) && ((exclusionMode | ExclusionMode.UpperBound) == ExclusionMode.UpperBound ? value < upperBound : value <= upperBound));
    }
}

我只是想解释甚至没有一个解决方案,它具有CodeContracts没有直接的源代码,但在IL操作呢?

Answer 1:

你需要的是完全有可能的,但没有多少人知道它。 首先,请在您的计算机上到C:\Program Files (x86)\Microsoft\Contracts\Languages\CSharp ,包括ContractExtensions.cs在您的项目。 它包含了你需要一些属性。

然后,应用ContractAbbreviator属性的方法。 您可以删除[Conditional("DEBUG")][ContractVerification(false)]的属性,你可以设置调试合同的行为,并在代码发布合同项目的属性页。 请注意,您必须调用您的合同法的方法,在那里你会写,否则合同的开始。 你不能把任何其他代码的方法。

public static class Assert
{
    [ContractAbbreviator]
    public static void GreaterThan<T>(T value, T lowerBound)
        where T : IComparable<T>
    {
        Contract.Ensures(value.CompareTo(lowerBound) > 0);
    }

    // ...
}

虽然这是一个回答你的问题,它可能不会解决你的问题。 其原因是,静态检测器不能看到当a.CompareTo(b) > 0a > b成立。 所以,这个例子不会与你的仿制版本工作,但将与您的非通用版本的工作:

static int PlusOne(int value)
{
    #region Contract
    Contract.Requires(value > 0);
    Assert.GreaterThan(value, 0);
    #endregion
    return value + 1;
}

编辑:

显然,我完全误解了你的意图Assert类。 事实上,你可以做什么建议在这个论坛 。

但是,你不能指望静态检查中了解到,例如,从x.CompareTo(y) > 0得出, x > y 。 原因? 你可以把这些方法字面上什么。 例如:

public int CompareTo(MyType t)
{
    // Implementation not consistent with '>'
    return this.field1 == t.field1 ? -1 : 1;
}

public static operator bool >(MyType left, MyType right)
{
    // Implementation not consistent with CompareTo()
    return left.CompareTo(right) <= 0;
}

你可能甚至都没有CompareTo 。 因此,静态检查也看不到它们之间的相似性。



文章来源: CodeContracts: Reuse of assumptions/asserts?