将文档放到代码里面,文档才会及时地更新!
微软从 .NET Framework 4.0 开始,增加了 System.Diagnostics.Contracts
命名空间,用来把契约文档融入代码。然而后面一直不冷不热,Visual Studio 都没天然支持。ReSharper 不知何时加入了 ReSharper Annotations,在 ReSharper 插件工作的情况下能够进行静态契约的验证。C#8.0 的可空引用类型是 Roslyn 对 null 的验证,本以为会带来编译级别的警告,没想到也只是契约。
契约式编程
当你调用某个类库里面的方法时,你如何能够知道传入的参数是否符合规范?如何能够知道方法调用结束之后是否要对结果进行判断?
T DoSomething<T>(T parent) where T : class;
▲ 对于上面的方法,你知道 null
传入参数是合理的吗?返回的参数需要判空吗?
代码的编写者可能是这么写的:
public T DoSomething<T>(T parent) where T : class
{
if (parent == null)
{
throw new ArgumentNullException(nameof(parent));
}
// 后续逻辑。
}
有些静态代码检查工具也许可以根据这里的参数判断代码块来认定为此处的参数不能为 null,但这种判断代码无处不在,静态检查工具如何能够有效地捕获每一处的检查呢?难道我们真的要去翻阅文档吗?然而除非是专门提供 SDK 的团队,否则文档通常都会滞后于代码,那么对于这些契约的修改可能就不太准确。
于是,契约式编程就应运而生。
它将前置条件(Precondition)、后置条件(Postcondition)、不变量(Invariant)等代码分离出来,按照特定的格式编写以便能够被