views:

94

answers:

1

I've been playing with the new System.Diagnostics.Contracts class because it seemed very useful at first. Static methods to check inbound arguments, return values, etc. It was a clean interface and could replace lots of if-then statements and internally built library tools.

However, it seems less than useful in most runtime situations. From what I can tell, it doesn't throw an error so I can't catch anything to know if a contract failed. It pops up a dialog box with the error. If I'm running a wcf service on a remote box that rarely has a human look at it...how would I know the contract failed? If I can't trap the fact that the error happened, how could I let the caller of the service know they f'd up?

Throw-Catch has been around for awhile, I don't understand why Contracts want to bypass this. Am I trying to use this thing incorrectly? If so, then someone give me a real-life situation where a runtime Contract makes sense. Ken

+6  A: 

From what I can tell, it doesn't throw an error so I can't catch anything to know if a contract failed.

If you need to throw a particular exception for calling code to catch, then you should use the Contract.Requires<TException> methods or legacy if-then-throws followed by Contract.EndContractBlock(). You'd do this when other code already expects and depends on regular exceptions being thrown, for example.

See Section 5.1: Argument Validation and Contracts of the user manual for a full explanation of when to use the different forms of precondition.

It pops up a dialog box with the error.

If you untick "Assert on Contract Failure" in the "Code Contracts" tab of your project settings, you will get an actual exception thrown at the offending point in code while debugging, rather than a dialog box. This is not for catching, however.

Throw-Catch has been around for awhile, I don't understand why Contracts want to bypass this. Am I trying to use this thing incorrectly? If so, then someone give me a real-life situation where a runtime Contract makes sense.

Section 7.5: Rational for Runtime Behaviour and Section 7.6: ContractException of the user manual explain why it functions this way.

The idea is that you should never need to write programs that contain specific logic that handles contract violations. They should never happen in correct programs and indicate a serious fault in the code that needs to be fixed. This is similar to how you should avoid catching ArgumentNullException.

You should still throw regular exceptions in exceptional circumstances that do not indicate faults in the code itself, such as when files could not be found. This allows the calling code to handle that circumstance as appropriate.

If I'm running a wcf service on a remote box that rarely has a human look at it...how would I know the contract failed?

Preferably, you should test the software as much as you can before putting it to use, to make sure that it never violates any contracts.

If you have a specific need to override the runtime behaviour, you can do so by writing your own contract runtime class. See Section 7.7: Providing a Custom Contract Runtime Class of the user manual for more information.

Edit: In response to the comment below...

You say it is meant to find faults in the code, but most faults in the code come from data passed in from outside sources, not the codes fault. And the software needs to both, log the fact that someone passed in bad data, and tell them they passed in bad data so they can fix it.

Preconditions are contracts that define when a method is allowed to be called, and are meant to be verified by the caller at the time of calling the method. The runtime checker will inject the appropriate checks in the calling code, not the method itself. If you have the static checker available, it will point out to you whenever you fail to ensure the preconditions before calling that method.

In your situation, your internal methods that process data should define preconditions stating what kind of data they allow. When data is passed in from outside sources that you cannot control, you should validate it and handle it in the usual way; you don't want to use code contracts for this. However, if for example you forget to fully validate that data, you will then encounter a contract violation when calling the internal code with preconditions. This indicates a bug in your own code.

Rich
Rich, thanks for taking the time. You didn't really make a case for the usefulness of Contracts though. You say it is meant to find faults in the code, but most faults in the code come from data passed in from outside sources, not the codes fault. And the software needs to both, log the fact that someone passed in bad data, and tell them they passed in bad data so they can fix it. Contracts don't seem to allow for this. Static contracts (compile time) make sense to me. Runtime Contracts, as implemented with the Diagnostics package, don't seem to fix anything. Still looking for the use-case.
Ken Foster
Check my updated answer for my response. The reply was too large to post as a comment.
Rich