.NET 4.0中代码合约的实际用途是什么?

36
为了充分理解和利用即将到来的新.NET Framework 4.0提供的新功能和增强功能,我想要一个代码契约实际应用示例。
  1. 有没有人有这个功能的好例子?

我想要一个带有简要说明的代码示例,以帮助我快速上手。

4个回答

24

来自《代码合同用户手册》:

使用代码合同,您可以在您的代码中表达前置条件、后置条件和对象不变量,以进行运行时检查、静态分析和文档编制。

代码合同用于静态验证; 想象一下-在编译时捕获语法错误和逻辑错误。这就是静态程序验证的愿景。

现实世界的例子

您可以使用合同(和静态验证)来减少测试成本...特别是回归测试成本。例如,假设我编写了一些代码以满足某些业务需求......但后来性能需求发生改变,我需要进行优化。如果我首先撰写一个合同,那么当我的新优化代码得到验证时,如果它不再满足原始合同,我将在我的IDE中收到一个错误消息,就像编译时错误一样。因此,您几乎立即找到并解决了错误,这比一轮测试成本更低。


JML4是Java的静态验证器,它允许您在注释中编写前置条件和后置条件(本质上是一个简单的合同)。对于那些感兴趣的人:http://sourceforge.net/apps/trac/jmlspecs/wiki/JML4 - Richard JP Le Guen

14

即将出版的书 C# in Depth, second edition 中有一章 自由提供的关于代码契约的内容。可能有些人熟悉 Jon Skeet 这个名字 :)

至于实际使用,你可以在代码的任何地方使用它们,但特别是如果你正在开发众多人将使用的框架/API类型库,则它们将非常有用。与在运行时发现未处理某些边缘情况相比,静态验证代码可以节省大量时间。

你可以随意记录方法使用,但人们真正会阅读那份文档吗?方法 y 中的字符串参数 x 是否允许为空?代码契约可以提供该信息,消除猜测。

以下是一个这样的例子:

static int CountWhitespace(string text)
{
    Contract.Requires<ArgumentNullException>(text != null, "text");
    return text.Count(char.IsWhiteSpace);
}

如果有人试图将可能为空的字符串传递给CountWhitespace,验证将会抱怨。此外,它会在运行时抛出ArgumentNullException。

我最近才将我的私有类库转换为.NET 4.0,但我计划很快添加代码合同。


你有一个现实世界的例子吗,就像楼主所要求的那样? - Robert Harvey
4
我链接的 PDF 文章里有很多例子,我可以把它们复制粘贴过来,但最好还是阅读整篇文章。请自行查看。 - Thorarin
+1 展示 Contract.Requires<TException>()。这是替代 if (x) throw y 代码块非常有用的方法。 - aaaantoine
好的,即使开发人员没有安装契约工具,这个错误能够正常运行吗? - Tony
提到的PDF文件在提供的链接中已不再可用。它只是重定向到该书的网页本身,该网页不再提供该章节的免费下载。 - Knowledge Cube

8

2
提供.NET Framework源代码以及使用Code Contracts的示例,绝对能够满足实际需求的要求。=)(+1) - Will Marcouiller

5

您是否曾经遇到过NullReferenceException,并希望编译器在编译时就能警告您,以避免程序崩溃而让您付出艰辛的代价?

通过代码合约,您可以编写如下内容:

Contract.Requires(foo != null);

这不仅是运行时检查 - 您可以设置它,以便如果您使用可能为空的参数调用此函数,则会出现编译错误。

以下是一个实际例子:

Address GetAddress(Customer customer)
{
    Contract.Requires<ArgumentNullException>(customer != null, "customer");
    return addressBook.FindCustomer(customer);
}

你有一个现实世界的例子吗,就像楼主所要求的那样? - Robert Harvey
2
为什么需要在第二个参数中再次将“customer”写成字符串? - Will Marcouiller
2
@Will Marcouiller:这不是必需的。如果提供了,它将用于错误消息。 - Mark Byers

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接