***** The content here originated from an email my coworker James sent around to our dev team, but I thought it was worth sharing everyone else with his permission *****
Summary: for the vast majority of cases, there is very little additional value in specifying a custom message in a contract call as the exception message will have the condition already.
When you are using the Code Contracts library there’s one bit of ‘magic’ involved in the Contracts support (specifically, the rewriting) that isn’t always obvious on the surface but can save a little bit of time and maintenance cost.
When doing ‘normal’ or ‘manual code for checking things (for instance, to potentially throw an exception), it is unfortunately common practice to basically have to repeat yourself when it comes to generating a user friendly error message. This is because the mechanism for conveying the problem (the exception’s Message property in a typical case) isn’t ‘automatically’ aware of the actual source of the problem. Take the code below for instance
If (foo < 0)
throw new ArgumentException (“foo cannot be less than 0”);
if (bar == null)
throw new ArgumentException (“bar cannot be null”);
(contrived, obviously, but you hopefully get the point)
However, the Code Contracts support includes rewriting an assembly, and as part of that effort, they include a nice feature of taking the conditional part and including the string version of it in the message for you.
In other words, writing just the condition still gets you an error that tells you what the condition was. You no longer have to repeat it!
Here’s an example of a Contract.Requires with no message:
The exception Message includes the condition without us having to do anything!
If you want to add a message to the call, that’s fine, but it’s important to note that since you’re already getting the condition, don’t put the condition (or a rephrased version of the condition) in the message. – the message should only be used if there’s additional useful information that could be conveyed. In the vast majority of cases, the condition itself is all you would want included in the message, so just not including your own message is all you need to do.
For instance, here’s a negative example where we’re restating the condition. We end up giving no additional value to the exception.
What’s worse is that if you *do* include a message, there’s nothing the compiler can do to enforce that the message is accurate in terms of the condition. It’s unfortunately common for someone to change the condition but forget to update the message. In such a case, you now have a confusing self-contradictory message.
The only ‘saving grace’ is that the condition will be included first, but that still requires the developer to know and understand why the message includes 2 conflicting pieces of information and which one to believe. Far better to just not include the message and everyone’s happy. J
For full details, you can read the code contracts documentation, but here’s the table from section 7.1, with the relevant bit being that the runtime check is done via a call that includes the condition in string form (what we saw above with the runtime behavior)
Hope this helps.
Till next time,
09-08-2011 2:19 PM