By this point in the series, you understand the basics of using Microsoft Code Contracts. And you probably have a high-level understanding of how to use the static checker given that we've focused our attention there in parts 1 through 5. In this part, however, we'll look for ways to instrument your code with contracts at runtime. The decision to use the Code Contracts runtime checker shouldn't be taken lightly. It requires understanding and careful preparation because it can fundamentally change the way your programs respond to contract failures.

When you first begin adding contracts to your code, it feels awkward. There are so many questions. Should I use the static checker? Should I use the runtime checker? Should I use both? If I need to throw specific exceptions on precondition failures, which form should they be coded in? If I use the runtime checker, how will the performance of my application be affected? What kinds of exceptions will I get if contract failures occur at runtime? If I decide not to use the runtime checker, do I need to test my code contracts since they won't emit Microsoft Intermediate Language (MSIL) in those cases? And if I decide to use only the static checker, how can I preserve the code contracts so that others can make decisions concerning their own tests and build processes later? What about those crazy ContractExceptions? I've read that you can't even catch those exceptions directly so what should I do about them?

The Code Contracts team at Microsoft recognizes that the choices can be overwhelming so they've identified three usage scenarios that can be selected by answering a couple of basic questions. Of course these aren't the only three valid scenarios but they are the ones that will likely cover most of the common cases. The following flowchart showing the questions and the usage scenarios appears the Code Contracts User Manual. Study the flowchart and I'll break it down for you below.

Decision flowchart from the Code Contracts manual

Why Isn't the Static Checker Described in the Flowchart?

Examining the three scenarios described in the flowchart, there's no mention of the static checker at all. This is because the decision to use the static checker is not directly related to your choice regarding the desired runtime behavior. Microsoft separated the two sets of tooling quite cleanly here. The tools you use at build time provide static analysis or verification while the runtime tools provide contract enforcement. These are two different concepts. Understanding that difference is a step toward Code Contract Zen. Does it make sense now why the options for checking implicit obligations are in the static checker section of the Visual Studio project properties page for Code Contracts? Deep analysis of the code to find unmet implicit obligations does little good in automated builds performed by a Continuous Integration (CI) server, for example. The output of the static checker is potent in the hands of human beings who can rationalize about converting implicit code obligations into explicit ones.

That's not to say that the static checker has no place in an automated build process. Including it there could serve as a last line of pre-release defense against classes of nasty bugs that creep into everyday code organically as it matures, especially if you've promoted warnings to errors in your CI process. But including the static checker in your CI builds without requiring your developers to use it uniformly can also create a roundabout way of breaking builds inadvertently, too. The rule of thumb here is that if you use the static checker in automated build scripts, you should also force your developers to build with a similar configuration before check-in.

Getting developers into the habit of evaluating the static checker's warnings and thinking critically about the obligations their code creates and those to which the code must yield is a good thing. Just be aware that the static checker does slow the build process down some. So if you force your developers to use it all the time, you may create some friction that lowers the perceived value of the tooling. In my experience, when you desire to use the static checker in automated builds, a happy medium can be found by asking your developers to perform a release build on their workstations just prior to check-in. Depending on your source control system, you might even have a way to script that around change sets.

Usage Scenario 1

This scenario is a good choice if you don't want any contract MSIL generated into release assemblies. Usage 3 is similar in this regard. The Requires() form of preconditions is recommended in this case because it generates code that will assert or throw a ContractException on failure when the runtime checker is enabled. But it emits no MSIL when the runtime tooling is disabled. You must disable the runtime checker in release builds to answer the question in the negative that led to this path: "Do you want argument validation in release builds?" No. The guidance here says to enable runtime checking on DEBUG builds but that has nothing to do with the question that was posed, does it? That's certainly an option but it's not required. If you enable the runtime checker for debug builds, you should also consider writing unit tests that exercise them.

The key thing to remember about the ContractException class is that it's marked internal to mscorlib (or the Microsoft.Contracts.dll assembly in .NET 3.5). So you can't catch a ContractException by name. You can't even refer to it by name in your unit tests. You can, of course, catch ContractException objects as Exceptions. The problem with marking an expected exception to be of type Exception is that you don't really know what the source of the exception was. A trick that I use inside my unit tests to make sure I'm encountering a contract related exception is to assert that for the caught Exception object named ex that ex.GetType().Name == "ContractException". You can further assert things about the exception's Message property which will contain the contract condition that failed. It's brittle, I know but if you're serious about testing your contracts, you'll do stuff like that.

One more thing to watch out for when unit testing your contracts: be sure to clear that checkbox in the runtime checking section of the Code Contracts project property page entitled "Assert on Contract Failure". If you check that option, the Code Contracts runtime will pop up a dialog box with contract failure information. This feature is really only useful when a human being is working through issues in a debug build. You should never enable the "Assert on Contract Failure" checkbox for a release build. Your customers won't understand what to do with this information, especially in this format.

Usage Scenario 3

That's right. I skipped scenario 2 because the third option is so much like the first one that I think it flows better to discuss things in this order. I'll get back to scenario 2 in a moment. The key difference with this option is that we desire argument validation at runtime. But by the way the questions were answered, we're saying that we don't want that support to come from the Code Contracts runtime tooling. So the advice is to use legacy style if-then-throw guard code and to mark the end of each guard code section with a call to Contract.EndContractBlock(). In release builds, those calls to EndContractBlock will evaporate, emitting no MSIL into your assembly. The if-then-throw code will remain and serve to protect against validation problems in the methods in which they reside but they won't technically be preconditions per se. It's just plain, old guard code that will throw exceptions of your choosing at runtime. As with scenario 1, the advice here is to enable the runtime tooling for debug builds only. The second question is also release build specific. So just as it was with the first question, it does not follow that the second question has anything to do with your decision concerning the runtime checker for your debug builds. It's just advice. Microsoft assumes that you'll want the runtime checker on all debug builds. But, of course, that's a choice you can make on your own, depending on your team's practices and your testing requirements.

Usage Scenario 2

When you definitely want runtime checking of contracts in your released code, usage scenario 2 is the one you want. If you use the Contract.Requires<TException>() form for preconditions, you must use the runtime tooling. If you don't those calls get translated into assertions that pop up dialogs in your code stating that you must use the runtime tooling. So if you forget, you will be reminded. The potential problem with tying the coding style to a build requirement is related to what happens when the source code written this way is included in two or more solutions that could be built with different runtime checker options. That's not really allowed. If you use the Requires<TException>() form, you must use the runtime tooling. For this reason, I prefer to use the legacy style if-then-throw preconditions in my code, even in this scenario. By definition, I am going to emit MSIL for the contracts in both my release and debug builds. So why not use a precondition form that allows other builders of my source code to make the runtime tooling choice that suits them best?

Runtime Checker Options for Usage Scenario 2

In closing, let's examine that last bullet point for scenario 2: use options to emit only preconditions and only on the public surface of the assembly. Public surface is a fancy way of saying "just the public members". The recommended settings for the runtime checker are shown in the image above. These can be found in the Code Contracts tab in the project's properties. The checkbox is enabled, turning on the runtime tooling. The combobox to the right of the checkbox has been set to "Preconditions" only. The default mode is "Full" which would cause all of the preconditions, postconditions, invariants, assumes and asserts to emit MSIL into the assembly. The preconditions only option will force the runtime rewriter to emit only the legacy style if-then-throw preconditions and both the Requires<TException>() and the Requires() type preconditions. But will following Microsoft's recommendations closely cause the Requires() type preconditions to be emitted or not? It's not a trick question but you have to look closely at the first two bullet points in the scenario 2 recommendations to answer it. They prescribe using the Requires<TException>() type preconditions in public methods and the Requires() type everywhere else. So if you enable the rewriter to emit code for the contracts in the public surface members only, then it follows that the Requires() type calls that would be used in non-public members would not be emitted. Wow, that makes me a bit dizzy. Tuning a few simple options and combining them with a variety of precondition types or styles that can be coded gives you fine-grained control over exactly what goes into your release builds and what goes into your debug builds. Learning how to use these bells and whistles takes some time and patience of course.

In my experience, when you use the runtime tooling for Code Contracts, it's always a good idea to limit it to the public surface methods. You should do everything you can to prove the correctness of your private, protected and internal members during design and testing. The public members, however, can be exercised by code written in the future and over which you have no control. Using the Code Contracts runtime tooling on them makes sense for the same reason that traditional guard code on public methods makes sense. For public methods, you can't be sure that the callers will understand their obligations so it's a good idea to have the runtime checker enforce some rules.

That's all for this post. It was devoid of code but I'll fix that in the next post when we'll continue expanding on the ideas introduced here by examining how to generate special assemblies called Contract Reference Assemblies. Some of the questions above about enabling consumers of your code in assembly form to make their own decisions about runtime support will be answered in that article. Until then, I hope you enjoy experimenting with code contracts!

This blog post is part of a series concerning Microsoft Code Contracts. For a complete series directory, please refer to the following list. Articles without a link will be published as they become available.