Search code examples
c#code-contracts

How to Handle Exceptions in Code Contracts in C#


I've started playing with Code Contracts for .NET.

  1. I have installed the msi.
  2. In my sample Console application, in project properties, I have set "Assembly Molde" to "Standard Contract Requires".
  3. I have checked "Perform Runtime Contract Checking" to "Full".

Having this settings, I'm using the very standard Contract.Require() in my code. I cannot put it in a try block, because it should be placed on the very top of the method's body. So, my question is how I handle the exceptions that it may throw, when the "Require()" condition is not satisfied?

With correct input, my code runs well, with the intended bad input, it throws an unhanded exception. I think I'm missing some pieces in the big picture here, or maybe my project's contract options are not set well.

Thanks for your help.


Solution

  • So, my question is how I handle the exceptions that it may throw, when the "Require()" condition is not satisfied?

    You never handle that exception in production code because that exception is never thrown in a correct program. The exception exists to tell the caller that they're doing it wrong and they cannot ship their code to customers until it is fixed. If the exception is never thrown then there is never any need to handle it.

    In test code, you do whatever your test framework does to represent "I expect this code to throw the following exception under the following error conditions".

    Now, these facts imply something about the design of your code which uses code contracts, namely, there must be a way for the caller to know that they're not going to violate the contract without trying it and catching the failure.

    I call exceptions thrown by badly-designed programs which require the caller to handle the failure "vexing exceptions". That is, you should never design a program like this:

    private Phase PhaseOfMoon() { ... }
    public void M()
    {
      Contract.Requires(this.PhaseOfMoon() != Phase.Full);
    

    See, the caller has no way of knowing what your private method is going to do, so the caller must catch the exception. You need to make sure that the caller always has a way to guarantee that the exception will not be thrown or the Require precondition will not be violated.

    In short: your responsibility is to give them a way to avoid the exception; their responsibility is to avoid it. No one's responsibility is to handle it.