Debug.Assert vs Code Contract usage

These are different things. A debug assert is only executed when the code is compiled as debug and therefore will only check/assert under debug. The idea is to use this for "sanity checks" for code you are developing. Code contracts can be used in either debug or release. They assure that pre and post conditions of methods comply with the expectations of the method (meet the contract). There is also a testing framework that provides similar functionality, designed for checking test compliance.

Use Debug.Assert when you want ensure that certain things are as you expect when developing the code (and in later maintenance development).

Use code contracts when you want to assure that conditions are true in both debug and release. Contracts also allow certain forms of static analysis that can be helpful in verifying that your program is "correct".

Use the Testing framework assertions when creating unit tests.


Personally, I wouldn't use both Debug.Assert AND Code Contracts to enforce preconditions in newly written code - IMO Code Contracts supercede Debug.Assert, as they offer a more comprehensive suite of checks, not to mention the benefit which can be gained from the static checking which can be performed before the code gets to run time. Maintaining duplicate precondition checks in both the Debug.Assert and Contracts will be cumbersome.

Rationale:

  • You don't need to re-code any legacy preconditions you may have coded in Debug.Assert or throw code - you can keep the existing precondition check code and terminate it with Contract.EndContractBlock()
  • You can get the same unchecked 'release mode' behaviour when System.Diagnostics.Debug is built without /d:DEBUG if you build with contract run time checking set to None. Ref 6.2.1 in the Docs
  • Contracts allows a dev to be more expressive in code as to 'why' an invalid state has been detected - e.g. was it directly because of an out of band parameter (Contract.Requires). Otherwise Contract.Assert or Contract.Assume can check general state, and the "guaranteed correctness" of state on leaving a method can be expressed using Contract.Ensures. And Invariants express that the state must be held at all times.
  • And best of all, Static checking can enforce these Contracts as you build your code - this way you have the chance to pick up the bug through a design time or compile time warning instead of having to wait for run time. Contract Checks can be added to your Continuous Integration to look for non-compliance.

One caveat : If you are going to write Unit Tests which deliberately violate contracts, you may need to deal with ContractException - Jon Skeet explains this well here. e.g. Wire up a Contract.ContractFailed handler in your test setup to a handler which calls SetHandled and then throws a public Exception which you can catch and assert in your UT's.