C# 共同合同:重复使用假设/资产?

C# 共同合同:重复使用假设/资产?,c#,assert,code-contracts,C#,Assert,Code Contracts,我已经在MSDN上发布了这篇文章,但是显然没有人知道或者费心去调查这个问题 我试图减少重复性断言,使其更加可重用,但不幸的是,这不起作用。你能解释为什么吗 [ContractVerification(false)] public static class Assert { [Conditional("DEBUG")] public static void GreaterThan<T>(T value, T lowerBound) where T : IComparab

我已经在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));
    }
}
[合同验证(错误)]
公共静态类断言
{
[有条件的(“调试”)]
公共静态无效大于(T值,T下限),其中T:I可比较
{
合同保证(价值比(LowerBond)>0);
}
[有条件的(“调试”)]
公共静态无效大于或等于(T值,T下限),其中T:I可比较
{
合同保证(价值比(下限)>=0);
}
[有条件的(“调试”)]
公共静态无效小于(T值,T上限),其中T:i可比较
{
合同保证(价值比(上限)<0);
}
[有条件的(“调试”)]
公共静态void LessThanOrEqual(T值,T上限),其中T:i可比较
{
契约.Contract(value.CompareTo(上限)0:value.CompareTo(下限)>=0)和&((排除模式|排除模式.上限)==排除模式.上限?value.CompareTo(上限)<0:value.CompareTo(上限)下限);
}
[有条件的(“调试”)]
公共静态无效大于或等于(int值,int下限)
{
合同保证(价值>=下限);
}
[有条件的(“调试”)]
公共静态无效小于(int值,int上限)
{
合同。确保(价值<上限);
}
[有条件的(“调试”)]
公共静态void LessThanOrEqual(int值,int上限)
{

Contract.surveures(value lowerBound:value>=lowerBound)和((exclusionMode | exclusionMode.UpperBound)==exclusionMode.UpperBound?valueC:\程序文件(x86)\Microsoft\Contracts\Languages\CSharp
并在项目中包含
ContractExtensions.cs
。它包含一些您需要的属性

然后,将该属性应用于您的方法。您可以删除
[条件(“调试”)]
[合同验证(false)]
属性,您可以在项目的“代码契约”属性页中设置调试和发布的契约行为。请注意,您必须在方法的开头调用契约方法,否则您将在此处编写契约。您不能在方法中放置任何其他代码

公共静态类断言
{
[合同修订人]
大于(T值,T下限)的公共静态空白
其中T:i可比较
{
合同保证(价值比(LowerBond)>0);
}
// ...
}
虽然这是对您的问题的回答,但可能无法解决您的问题。原因是静态检查器无法看到,
a>b
保持不变。因此,此示例不适用于通用版本,但适用于非通用版本:

static int PlusOne(int值)
{
#区域合同
合同要求(价值>0);
Assert.GreaterThan(值为0);
#端区
返回值+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;
}
public int CompareTo(MyType t)
{
//实现与'>'不一致
返回this.field1==t.field1?-1:1;
}
公共静态运算符bool>(MyType左,MyType右)
{
//实现与CompareTo()不一致

返回左侧。比较到(右侧)我已经写过了,它使用的是非通用版本,我知道。自从发布以来,我一直在使用CodeContracts,我知道你的示例不起作用,静态检查程序会对这些断言提出抱怨,因为ContractAbreviator只使用requires,而从来没有为确保或其他任何东西而设计。在你身上例如,在合同没有意义的情况下,你断言,断言是在调用它之后的另一个函数的输出。你的例子是有效的,因为静态检查器已经验证了输入,中间没有返回需要断言的任意值。请此人告诉我为什么通用版本不起作用?为什么它看不见?限制是什么?你看错了。
contractAbreviator
可以同时满足要求和保证。只有使用
contractAbreviator
属性,
greater
中的合同插入方法的正确位置d调用。它不是断言(但您称之为
Assert
),也不是在合同之后。它是合同的一部分。
PlusOne
在我的示例中有一个要求和一个确保(通过
大于
).最后,
GreaterThan
将永远不会被调用,只会复制合同。我告诉过你为什么检查器不能同时使用
CompareTo
和比较运算符。好吧,我仔细检查了一下,你是对的,ContractAbreviator可以为您工作,但我并没有直接将其命名为assert,它们实际上用于当我在CodeContracts论坛上特别问我如何创建可重用的假设时,告诉我这样做的人是Francesco。当我使用ContractAbreviator时,它不能像预期的那样工作,因为静态检查器在不应该的时候抱怨,它应该像我使用C一样工作假设上面的实现做得很好,恕我直言,你没有告诉我任何新的东西
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;
}