代码契约
来源:互联网 发布:mac如何修改登录密码 编辑:程序博客网 时间:2024/04/28 00:43
代码契约之于C#语言,就相当于诗歌之于自然语言。
代码契约能从根本上改变代码的外观和所传达的信息量。
——《深入理解C#》(第二版)
Code Contract for .NET
使用之前必须先安装Code Contract for .NET,可以在
https://visualstudiogallery.msdn.microsoft.com/1ec7db13-3363-46c9-851f-
1ce455f66970下载,安装之后visual studio的项目属性页中多了一页“Code
Contract”。
代码契约类型
前置条件
前置条件(Precondition)是对方法调用者提出要求,而不是表示普通条件下方法本身
的行为。我们总是坚信自己的代码没有问题,但却不能信任外部代码,因此前置条件是
已有程序中最常见的契约代码。前置契约使用Requires方法实现。
2
3
4
5
public static double Sqrt(double x)
{
Contract.Requires(x >= 0);
return Math.Sqrt(x);
}
如果你在一个公共public方法中,对一个私有private变量使用前置条件契约,编译器会
直接报错,因为这样做对调用者是不公平的。
后置条件
前置条件是对方法输入或对象的原始状态的约束,而后置条件(Postcondition)是对方
法输出的约束:返回值、out或ref参数的值,以及任何被改变的状态。后置条件使用
Ensures方法实现。
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
{
int m_nState = 0;
//检查返回值。
public int Func1(int x)
{
Contract.Ensures(Contract.Result<int>() > 0);
m_nState–;
return x * 5;
}
//检查out参数,ref参数方法一样。
public void Func2(int x, out int y)
{
Contract.Ensures(Contract.ValueAtReturn<int>(out y) > 0);
m_nState++;
y = x * 3;
}
//检查本地状态
public int Func3(int x)
{
Contract.Ensures(Contract.ValueAtReturn<int>(out
m_nState) > 0);
return x + 1;
}
}
后置条件的实现需要Contract.Result<T>()和Contract.ValueAtReturn<T>两个方法配
合实现。
后置条件最神奇的地方是契约代码写在return语句之前,可以省去定义一个临时变量存
放要返回的值,再对这个临时变量进行检查(手工断言)。这是代码契约与手工断言之
间最重要的区别。
固定条件/对象不变量
尽管叫invariant,但它并不表示一个保持不变的值,而是表示一个总是满足的固定条件
。例如一个字符串变量,在它可以在对象的生命周期内被不断修改,但永远满足不为空
的条件。固定条件可以在任何方法结束时进行自动检测,而不毕为防止出错,在每个方
法结束时对该变量进行检测。
固定条件的使用必须顶一个检测方法:必须是私有方法Private,必须用
ContractInvariantMethod特性修饰。
2
3
4
5
[ContractInvariantMethod]
private void CheckState()
{
Contract.Invariant(m_nState > -10 && m_nState < 10);
}
断言和假设
Assert和Assume,如果不使用静态检查器,二者没有区别,它们和Debug.Assert方法类
似,在执行时检查某个条件是否为真。静态检查器处理这二个方法时略有不同,他会检
验断言是否为真,却不会处理假设。
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
Contract.Ensures(Contract.Result<int>() >= 2);
Contract.Ensures(Contract.Result<int>() <= 12);Contract.Assert(rng !=null);
int firstRoll = rng.Next(1, 7);
Contract.Assume(firstRoll >= 1);
Contract.Assume(firstRoll <= 6);
int seconfRoll = rng.Next(1, 7);
Contract.Assume(seconfRoll >= 1);
Contract.Assume(seconfRoll <= 6);return firstRoll + seconfRoll;
}
- 代码契约
- CLR 4.0中的代码契约
- 契约
- 代码优先与契约优先的比较
- 契约(服务契约)
- 契约(数据契约)
- 契约(消息契约)
- 魔鬼契约
- WCF契约设计: 服务契约,数据契约和消息契约
- 数据契约
- 消息契约
- 契约精神
- WCF 契约
- 契约精神
- 契约介绍
- WCF契约之---服务契约 、数据契约、 消息契约
- laravel--契约
- 对于开发 0 bug 代码的思考——Design by Contract 契约设计
- 0-1背包问题---回溯法
- 第十一周项目1 (2) 函数版小星星
- win7驱动开发 VMWare+Windbg的虚拟机双机内核调试环境(VS2008+DDK)
- HDU 1.3.2 Tian Ji -- The Horse Racing
- 服务器端负载均衡技术的本质原理
- 代码契约
- Unity3D中的SendMessage
- 第十一周项目1(3)调用函数输出字母
- C# 文件操作,遍历文件夹、读文件、写入、修改、复制
- box-sizing 的相关解释
- http://blog.csdn.net/enuola/article/details/8099461
- 账号登陆加密流程
- java使用查表法+组合数学 求水仙花数
- IOS界面UI设计2之屏幕适配AutoLayout、size classes(一)