45

When should I debug.assert over code contracts or vice versa? I want to check precondition for a method and I am confused to choose one over the other. I have unit tests where I want to test failure scenarios and expect exceptions.

Is it a good practice to use Debug.Assert and Code contract on the same method. If so what would be the order in which the code should be written?

Debug.Assert(parameter!= null);
Contract.Requires<ArgumentNullException>(parameter != null, "parameter");

or

Contract.Requires<ArgumentNullException>(parameter != null, "parameter");
Debug.Assert(parameter!= null);

Is there any rationale behind it?

Carbine
  • 7,849
  • 4
  • 30
  • 54

2 Answers2

37

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.

Dweeberly
  • 4,668
  • 2
  • 22
  • 41
  • I totally agree, but if I choose to use debug.assert and code contract on the same place should it be in certain order? – Carbine Dec 16 '13 at 04:58
  • Not sure why you would do a double check in that manner. Order shouldn't manner. If I were doing that I believe I'd put the Debug.Assert first as a development debugging aid. – Dweeberly Dec 16 '13 at 14:29
  • Debug.Assert will not be there in Release code, but code contracts will. So I feel there are cases where debug.assert will be needed in parallel with Code contracts- I might be wrong. Hence the question. – Carbine Dec 16 '13 at 15:09
  • 3
    True, but the code contract will detect the issue it both debug and release. If you make sure to break on code contract exceptions you have the same effect without the need for the Debug.Assert. One could make a case that having a debug.Assert in addition to code contract does provide a double check for maintenance (Asserts are hard to ignore :-)) – Dweeberly Dec 20 '13 at 22:48
  • 9
    Not to be forgotten: "Use the `Trace.Assert` method if you want to do assertions in release builds." (http://msdn.microsoft.com/en-us/library/tk4kachs(v=vs.110).aspx) – heltonbiker Aug 21 '14 at 20:45
28

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.

StuartLC
  • 104,537
  • 17
  • 209
  • 285
  • 2
    Nice explanation. Now I get it. If used consistently, it brings so much clarity to what the developer assumes about the state of the application all along the way. And that's just icing on the cake, the cake being more detailed and complete exception handling routines that are easy to put in right from the begining. – jeremcc Mar 24 '14 at 13:12
  • Only if there was a solution-wide configuration setting to make sure `Contract.Assert`s don't end up in Release build I would use them. Otherwise I use `Debug.Assert` because I know they will never leak into Release build. Configuration maintenance of Code Contracts is its biggest drawback IMO. – orad Aug 28 '14 at 20:00
  • Adding to my previous comment, for pre-conditions and post-conditions on public interfaces I see why we would want to include them in release mode for use of the consumer code. But I don't see any reason why we would want to include asserts in release mode in any case. I may not be informed enough about that. – orad Aug 28 '14 at 20:14
  • A contract failure means that an assumption about code state has failed - something has slipped past validation defences. Even in production I would want to know about this and stop executing. In most instances I would willingly sacrifice some performance for this checking. – StuartLC Dec 19 '15 at 18:36