问题
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?
回答1:
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.
回答2:
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
orthrow
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 toNone
. 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
). OtherwiseContract.Assert
orContract.Assume
can check general state, and the "guaranteed correctness" of state on leaving a method can be expressed usingContract.Ensures
. AndInvariants
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.
来源:https://stackoverflow.com/questions/20603510/debug-assert-vs-code-contract-usage