我想在我最新的C#应用程序中通过契约尝试一点设计,并希望语法类似于:
public string Foo() { set { Assert.IsNotNull(value); Assert.IsTrue(value.Contains("bar")); _foo = value; } }
我知道我可以从单元测试框架中获取这样的静态方法,但是我想知道这样的东西是否已经内置于该语言中,或者是否已经存在某种类型的框架.我可以编写自己的Assert函数,只是不想重新发明轮子.
C#4.0代码合同
Microsoft已经在.net框架的4.0版本中发布了一个按合同设计的库.该库最酷的功能之一是它还带有静态分析工具(类似于我猜的FxCop),它利用了您对代码签订的合同的详细信息.
以下是一些Microsoft资源:
主要的微软研究网站
用户手册
2008年PDC演讲
2009年PDC演讲
以下是其他一些资源:
.NET 4.0的代码契约 - 规范#活跃起来
.NET代码合同和TDD是互补的
代码合同入门 - 第5部分:利用对象不变量
代码合同入门 - 第6部分接口合同
Spec#是一个流行的微软研究项目,它允许一些DBC结构,比如检查post和pre条件.例如,二进制搜索可以使用前置条件和后置条件以及循环不变量来实现.这个例子还有更多:
public static int BinarySearch(int[]! a, int key) requires forall{int i in (0: a.Length), int j in (i: a.Length); a[i] <= a[j]}; ensures 0 <= result ==> a[result] == key; ensures result < 0 ==> forall{int i in (0: a.Length); a[i] != key}; { int low = 0; int high = a.Length - 1; while (low <= high) invariant high+1 <= a.Length; invariant forall{int i in (0: low); a[i] != key}; invariant forall{int i in (high+1: a.Length); a[i] != key}; { int mid = (low + high) / 2; int midVal = a[mid]; if (midVal < key) { low = mid + 1; } else if (key < midVal) { high = mid - 1; } else { return mid; // key found } } return -(low + 1); // key not found. }
请注意,使用Spec#语言会产生DBC结构的编译时检查,对我来说,这是利用DBC的最佳方法.通常,依赖于运行时断言会成为生产中的头痛,人们通常会选择使用异常.
还有其他语言将DBC概念作为第一类构造包含在内,即Eiffel也可用于.NET平台.
除了使用外部库,您在System.Diagnostics中有一个简单的断言:
using System.Diagnostics Debug.Assert(value != null); Debug.Assert(value == true);
我知道,不是很有用.
.net Fx 4.0中有一个答案:
System.Diagnostics.Contracts
http://msdn.microsoft.com/en-us/library/dd264808.aspx
Contract.Requires(newNumber > 0, “Failed contract: negative”); Contract.Ensures(list.Count == Contract.OldValue(list.Count) + 1);