I need to know examples of how and where you are using assertions in c#.
EDITI need practical examples of where its most appropriate to use assertions. Thats why I need examples from those who have used them
-
The immediate answer I can think of is when you are testing code:
Assert.IsNotNull(yourVariable);
You can also use the Debug.Assert
System.Diagnostics.Debug.Assert(myBooleanProperty);
-
Google should give you plenty of examples (hint: type csharp example assert)
-
I prefer to use unit tests to flesh out problems. Since my main product is a library/assembly, it's also necessary to make sure that arguments are validated and appropriate exceptions thrown.
Interesting note: Debug.Assert() is trapped by the MS C# compiler in a release build and removed.
-
There was a good discussion about the usage of Debug.Assert() a while back: http://stackoverflow.com/questions/506285/debug-assert-vs-exceptions
-
Of course in unit tests.
Outside unit tests I can identify 3 types of errors (very simplified):
- Critical internal error: Something that comes from inside of your code unit, that the user has no way to influence.
- Misuse of some functionality: For example giving a null instead of some value
- External problems: Such as non-existing file, no network connection, etc.
I think that assertions should be applied only to the first one. Number two and three should be handled using appropriate exceptions.
-
I really like to support exceptionhandling during debugtime by using Debug.Assert() or even Debug.Fail():
if( !whatever_I_expect ) { var message = "<exception message>"; Debug.Fail( message ); throw new InvalidOperation( message ); }
This way I get the very handy dialog of Debug.Assert() and can choose between ignore, retry and abort. Retry will step into the code where I can start debugging. Especially recursive methods or complicated try-catch constructions can be better debugged this way. You always get the right call stack. And in my releasecode I still have a valid errorhandling without messageboxes.
-
I often use Debug.Assert for checking preconditions for my code. If an object depends on another object being present I might assert this other object is not null for example. This makes lots of problems visible even before I hand my programs to testing.
There's a fine line between what I'd want to check with unit tests and what I want to check during runtime with assertions. Usually unit tests are for testing a single unit of code when the rest of the application is in a well defined state (I use mock objects for this extensively) and I use debug.assert to check during runtime if the state of the application is as I expected.
-
Our current strategy at work:
- Public/Protected members: Invariants checked and throw exceptions, return invariants tested with Debug.Assert
- Private members: Argument invariants checked using Debug.Assert, all other invariants checked and throw exceptions
- Other situations: Any operational invariant we absolutely cannot violate gets an exception thrown, any operational invariant we shouldn't violate gets a Debug.Assert, etc
What this allows is for the release application to trudge along and quite possibly fail and get trapped in the unhandled exception handler, however, because we've been liberal with Debug.Assert statements we should have already caught this failure in testing. Regardless, we can turn on the checked build (+debug) and view the assertion before any exception gets thrown.
Example:
public RetVal MyMethod(T1 arg1, T2 arg2, ..., Tn argn) { Guard.ArgumentIsNotNull(arg1, "arg1"); Guard.ArgumentIsNotNullOrEmpty(arg2, "arg2"); // ... more of those sorta test // ... internal check for something that must be true/false at this point Debug.Assert(operationalInvariant, "Operational invariant ... failed ..."); // ... sanity upon return Debug.Assert(retValInvariant, "Return value failed invariant ..."); return retVal; } private void OtherMethod(T1 arg1, T2 arg2, ..., Tn argn) { Debug.Assert(arg1 != null); Debug.Assert(!String.IsNullOrEmpty(arg2)); // ... do work if (methylEthylBadStuff) throw new InvalidOperationException(); // ... }
-
There are different views (see recent sub-thread in comp.lang.c++.moderated, subject "We do not use C++ exceptions").
I take the view that assertions are best to check and document things that you know cannot be false, unless the implementation is inconsistent. This is stronger than pre-conditions and invariants.
E.g. that a helper function, which can only be called from a couple of different places, has a resource available. Because this helper is private and only used inside one class throwing an ArgumentException is not appropriate (that's for the public/protected interface).
-
I used Debug.Assert() quite a bit in code that should never receive a bad/invalid parameter - the kind of code where the input parameters and dependant variables should have already been validated. Truth is, I know I'm going to make mistakes. I just don't know where. :-) Judicous use of "Debug.Assert" helps me cope with my imperfections.
Here's an example from my own code:
public bool AddPoint(uint time, object value) { bool success = false; int index = 0; Debug.Assert(_selectedParameterName != null, "RecipeBusinessObject.InsertPointAtTime() _selectedParameterName = null"); Debug.Assert(_currentRecipe != null, "RecipeBusinessObject.InsertPointAtTime() _currentRecipe = null"); Debug.Assert(CurrentParameterTable != null, "RecipeBusinessObject.InsertPointAtTime() CurrentParameterTable = null"); Debug.Assert(index >= 0, "RecipeBusinessObject.InsertPoint(), index out of range, index = " + index.ToString()); Debug.Assert(index <= CurrentParameterTable.Rows.Count, "RecipeBusinessObject.InsertPoint(), index out of range, index = " + index.ToString()); DataRow newRow = CurrentParameterTable.NewRow(); <snip>
0 comments:
Post a Comment