gpt4 book ai didi

c# - 代码契约(Contract) : How to express these conditions?

转载 作者:太空狗 更新时间:2023-10-30 01:07:07 26 4
gpt4 key购买 nike

我目前正在研究代码契约,我不完全确定契约类的静态方法是否强大到足以与条件的数学符号竞争。

假设我们有一个简单的阶乘方法

int Factorial(int n);

我要表达以下条件:

Precondition:
n >= 0

Postconditions:
Factorial(n) = 1, in case n = 0
Factorial(n) = n*(n-1)*...*1, in case n > 0

这些条件以简洁明了的方式清楚地指定了 Factorial 的行为。我的问题是,它们是否可以通过代码契约来表达。

先决条件很简单:

Contract.Requires(n >= 0)

条件发布条件可以使用

表示
if(n==0)
Contract.Ensures(Contract.Result<int>() == 1);
if(n > 0)
...

但我不喜欢这里需要“if”语句的方式,因为它使前置条件和后置条件的简单列表更难阅读。我希望我们能有类似的东西

Contract.Ensures(...).InCase(...);

最后但并非最不重要的是,我不知道如何表达这个,这是关于数学的常见符号:

n*(n-1)*...*1

我猜我需要某种循环,但这会复制整个实现。有什么聪明的方法来表达这样的符号吗?

提前谢谢你。

最佳答案

您正在寻找的是单元测试,而不是代码契约。

通常,像if n=0, then f(n) = 1if n=3, then f(n) = 6 这样的检查是测试用例应表示为单元测试。

在您的情况下,我认为合适的后置条件类似于“结果总是 >= 1”。仅此而已。

假设您的阶乘类看起来像这样:

public class Factorial
{
public int Compute(int n)
{
if (n == 0)
return 1;

return n * Compute(n - 1);
}
}

NUnit Framework 编写的合适的单元测试会是:

[TestFixture]
public class FactorialTests
{
[TestCase(0, 1)]
[TestCase(1, 1)]
[TestCase(2, 2)]
[TestCase(7, 5040)]
[TestCase(10, 3628800)]
public void Compute_ReturnsCorrectResult(int n, int expectedResult)
{
var sut = new Factorial();

Assert.AreEqual(expectedResult, sut.Compute(n));
}
}

更新(评论后)

Stating result >= 1 does not fully specify the algorithm.

我不认为代码契约的工作是详细指定算法。算法由方法指定。

如果代码契约是一个复杂的逻辑片段,就像方法本身一样,那么我想我们需要一个代码契约来验证代码契约是否执行了正确的检查。这显然会导致无限递归。

I didn't expect n*(n-1)*...*1 to be accepted by the compiler. But some generic range operator in a LINQ-flavoured way would surely be a gread addition, e.g. From(n).To(1).Product() or From(n).To(m).Sum()

如果存在这样一种表达阶乘的形式(很可能存在),您当然可以在您的代码中使用它,而不是在代码契约中使用它。

更新 2

为了好玩,我找到了一种计算阶乘的 LINQ 方法:

Enumerable.Range(1, n == 0 ? 1 : n).Aggregate((a, i) => a * i);

关于c# - 代码契约(Contract) : How to express these conditions?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13469379/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com