Fog Creek Software
Discussion Board




Assertions in C#

When do you use Debug.Assert in C#? I'd particualrly like to hear Joel's take on this.

Fry
Friday, December 05, 2003

I use an assert whenever I make an assumption that has any chance of being wrong.  For example if I write a function that other developers will call, I use asserts to make sure the arguments aren't null.  I also like to use them in switch statements in the 'default' case (debug.assert(false)).  This is very useful when checking all values of an enum.  If you add another enum then the assert will tell you right away that you need to add the case to the switch statement.

Kev
Friday, December 05, 2003

I wouldn't use Debug.Assert or Trace.Assert to check for null/invalid arguments: I'd explicity check the arguments and throw an ArgumentNullException or an ArgumentOutOfRangeException.

Otherwise use Debug.Assert liberally for almost any assumption (it's only included in debug builds).  Use Trace.Assert for important assertions that you want to catch in a release build (VS enables tracing by default -use /d:TRACE if using the compiler from the command line)

Joe
Friday, December 05, 2003

Use both--assertions and exceptions. The problem with throwing an exception is some calling function might catch it and silently recover. Then you'd never know about your bug. But using an assertion guarantees you'll be made aware of the bug.

Anon. Coward
Saturday, December 06, 2003

> Use both--assertions and exceptions.

This seem like a good idea. But the problem is when you create the ship version, the caller of your function might not handle the exception because it was never encountered in the debug version.

I've always thought assertions and exceptions contradict in some way. When should you use exceptions and when assertions? And when should they overlap?

Fry
Sunday, December 07, 2003

Exceptions should be used to test conditions that an external client (where "external" is relative to the current code unit) might get wrong. Typical case: supplying null references in parameters where none are allowed, or trying to open a nonexistent file.

Exceptions also specifically allow for the client to catch & handle them, which is why it's wrong to test the same condition with an assertion. That is, exceptions should also be used for conditions that the client might expect to fail and will be prepared to handle.

Assertions should be used when none of the above applies -- that is, for condition testing within a code unit (you won't handle failure anyway and you want maximum speed in release mode), or for testing conditions that cannot possibly fail except due to a fatal programming error.

Usually, assertions verify conditions that were already guarded by exceptions higher up the call tree, or during data initialization etc.

Short version: use exceptions for conditions that MIGHT fail, use assertions for conditions that CANNOT possibly fail, except due to catastrophic bugs.

In time-critical code, there's also the point that Debug.Assert will be removed in release mode so you save a little time compared to exceptions. But you should only use assertions to save time where it's really necessary.

Chris Nahr
Sunday, December 07, 2003

Chris, can you give a concrete example of when to use Assertions?

If I am not mistaken, it would seem that you find assertions almost useless if you are already using the exception model.

Fry
Sunday, December 07, 2003

A common use of assertions would be to check that a variable holds a valid value at the end of the method that computed this value.

Another common use would be to check the value of some private data at the beginning of a method that requires this data. However, if the caller was in some way responsible for properly setting this data you should use an InvalidOperationException instead.

Yes, you can replace all assertions with exceptions if you want to. But using assertions when they are adequate is (a) clearer to the reader of your code because it says "this condition is an invariant that should never fail regardless of the client's antics", and (b) faster because .NET removes all Debug method calls in release builds.

Chris Nahr
Tuesday, December 09, 2003

I should probably add that you'll only need assertions if your code reaches a certain complexity. E.g. you know that variable A should be either -37 or +42 at some point but the instruction flow up to that point is so complicated that you can't easily trace it at a glance. That's when you use an assertion to make sure your program works correctly.

There's not much  point to using assertions in simple and obvious code that doesn't do much internally, like a simple data entry screen. In that case, just use exceptions to test external conditions (parameter values, file system state, and the like).

Chris Nahr
Tuesday, December 09, 2003

*  Recent Topics

*  Fog Creek Home