Code Contracts 是微软对 Programming By Contract 的实现,.NET Framework 4.0和4.5都提供了相应的类库支持。在mscorelib.dll的System.Diagnostics.Contracts 名字空间下定义了Contract类,它包含了一组静态方法用来定义各种Contract,例如:Contract.Requires, Contract.Ensures等 。但是,光有这些定义Contract的代码还是不够的,你还有在你的工程中启用Runtime或者是Static Contract检查才可以。否则,你就会在运行时看到如下的错误信息:
对应的执行代码如下:
using System;
using System.Diagnostics.Contracts;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Divide(12, 1);
}
static int Divide(int number, int divisor)
{
Contract.Requires<InvalidCastException>(divisor != 0);
return number / divisor;
}
}
}
看了很多遍,感觉这段错误提示是相当难懂,让人不知到底是为什么会有这个错误,该如何修复。经过多次实验以及在网上搜索到信息,才搞明白最关键的部分要通过选择 'Enable Runtime Contract Checking' 来定义 CONTRACTS_FULL。可是,同样是使用Contract.Requires调用,下面的代码却不会上面的错误:
class Program
{
static void Main(string[] args)
{
Divide(12, 1);
}
static int Divide(int number, int divisor)
{
Contract.Requires(divisor != 0);
return number / divisor;
}
}
看来问题关键在于 Contract.Requires()和 Contract.Requires<>() 方法的定义是不一样的。通过.NET Reflector,可以进一步看清两者是如何定义的。 Requires()上定义了 [ConditionalAttribute("CONTRACTS_FULL")] 属性,这样编译器就可以根据CONTRACTS_FULL标识是否定义来决定Requires()是否可用;而Requires<>()没有该属性,所以它在CONTRACTS_FULL未被定义的情况下也仍然可用,所以就会出现上面的错误。
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail), Conditional("CONTRACTS_FULL"), __DynamicallyInvokable, TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
public static void Requires(bool condition)
{
AssertMustUseRewriter(ContractFailureKind.Precondition, "Requires");
}
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail), __DynamicallyInvokable, TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
public static void Requires<TException>(bool condition) where TException: Exception
{
AssertMustUseRewriter(ContractFailureKind.Precondition, "Requires<TException>");
}
这也是问什么在Requires<>()的文档中重点强调了 - " You must turn on run-time checking to use theRequires method. If run-time checking is turned off, the process will be terminated. To obtain the tools for runtime checking, seeCode Contracts on the MSDN DevLabs Web site. "
参考