![]() |
Web Development »
Trace and Logs »
Debug and Tracing
Intermediate
I take exception to that argument!By Nils JonssonAchieve greater consistency in raising argument exceptions with very little effort. This utility class (which is covered by nearly 600 included NUnit test cases!) makes it possible to evaluate and raise exceptions on passed-in parameters, using a single line of code. |
C#, Windows, .NET 1.1VS.NET2003, Dev
|
|
Advanced Search Add to IE Search |
|
|
|
||||||||||||||||
Admit it: you�re probably more lax than you should be about parameters that get passed into the class members you write. Laziness strikes every developer from time to time. I myself got tired of typing the following code every other minute:
if (value == null)
throw new ArgumentNullException("value");
I got lazy enough that I decided to make testing member arguments and raising exceptions on them as effortless as possible. The result of my laziness is a utility class that makes it easy to be strict about what you allow callers to pass into your code.
Since this code is likely to be of use in every part of most of your C# projects, I also went to the trouble of writing nearly 600 NUnit test cases that you can run to verify my code�s correctness and to get a feel of how to call this utility class from your code. (See Testing the code below, for information on how to run the test cases.)
This utility class is designed to be included in your C# projects, not referenced as a compiled assembly. The reasons for this should be obvious, but you definitely don�t want dozens of copies of a C# source file all over your source tree. So put the file in the root of your source code directory and make a link (see below) to that one file in each of your C# projects.

Exceptions.cs has nine static methods (most of them heavily overloaded) that test for argument constraint violations and throw the appropriate standard argument exception. The methods are thoroughly documented in XML documentation comments within the source and in an HTML Help file generated from those comments. Examples are included in the documentation to show how the methods can be used most effectively in your code�everything from implementing IComparable, to extending CollectionBase, to argument validation in constructors, methods and properties. Briefly summarized, the methods are:
ThrowIfDifferentRank() throws RankException if an array argument does not have a given number of dimensions.
ThrowIfDifferentType() throws ArgumentException if an argument is not an instance of a given type.
ThrowIfIncompatibleType() throws ArgumentException if an argument cannot be cast to a given type.
ThrowIfInvalidEnumValue() throws InvalidEnumArgumentException if an argument is not a constant in a given enumerated type.
ThrowIfNull() throws ArgumentNullException if an argument is a null reference (Nothing in Visual Basic).
ThrowIfOutOfRange() throws ArgumentOutOfRangeException if an argument is less than a given minimum or greater than a given maximum.
ThrowIfOutOfRangeExclusive() throws ArgumentOutOfRangeException if an argument is less than or equal to a given lower bound or greater than or equal to a given upper bound.
ThrowIfOutOfRangeIncludeMax() throws ArgumentOutOfRangeException if an argument is less than or equal to a given lower bound or greater than a given maximum.
ThrowIfOutOfRangeIncludeMin() throws ArgumentOutOfRangeException if an argument is less than a given minimum or greater than or equal to a given upper bound. It�s good defensive programming practice to sprinkle Debug.Assert() liberally throughout your code in order to exterminate bugs before they crawl around and lay eggs. You might be wondering when you should opt to throw an exception instead of asserting a condition.
Here�s a rule of thumb:
private and internal members, call Debug.Assert().
protected, protected internal and public members, call Exceptions.ThrowIf� and/or throw custom exceptions. My rationale is that code running in a different assembly should be given the opportunity to catch properly formatted exceptions. Assertions are for internal use only�housekeeping notes to yourself. Keep in mind that they don�t even get evaluated in release builds.
There�s no reason why you should trust that this code will do what it�s supposed to do. In fact, there�s little reason, apart from rigorous testing, why you should trust any source code in your projects, whether you wrote it or somebody else did. If the word �testing� sounds to you like somebody else�s job, then you�re passing the buck. And you�re also missing out on a way both to drastically improve the quality of your code and to reduce your stress about the quality of your code. Sounds impossible? Read about Alphonse (read the rest of the series, too) for an entertaining introduction to test-driven development. The XP gurus have informative things to say about TDD, too.
Whether you�re new to automated unit testing or are an experienced user of NUnit, MbUnit or other unit-testing frameworks, you should download and install a wonderful Visual Studio .NET add-in called TestDriven.NET. It provides a �friction-free� developer experience for running unit test cases from within the Visual Studio .NET 2003 IDE. You don�t need the other frameworks installed first; it comes complete. In fact, you might want to uninstall NUnit and MbUnit before installing TestDriven.NET.
Seriously: download it and install it right now. I�ll wait.
Back already? With TestDriven.NET installed, open the solution, Umbrae.Exceptions.Test.sln, in Visual Studio .NET 2003. Then right-click on ExceptionsTest.cs in the IDE and click the Run Test(s) menu item.

You should be able to see all the tests execute successfully in the IDE�s Output window:
------ Test started: Assembly: Umbrae.Exceptions.Test.dll ------
558 succeeded, 0 failed, 0 skipped, took 8.98 seconds.
---------------------- Done ----------------------
I welcome your input on this, whether it be bug reports, flames, enhancement ideas, or unit tests I�ve neglected to write.
DebuggerHidden attribute to all Exceptions members that throw exceptions.
Debug.Assert() calls in Exceptions.cs.
ExceptionsTest.TemporaryTypeBuilder.CreateEnumTypeWithFlagsAttribute().
ThrowIfDifferentRank().
ThrowIfNull() to avoid unnecessarily composing the Message property.
Debug.Assert() vs. throwing exceptions.
| You must Sign In to use this message board. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
General
News
Question
Answer
Joke
Rant
Admin
|
PermaLink |
Privacy |
Terms of Use
Last Updated: 30 Dec 2004 Editor: Smitha Vijayan |
Copyright 2004 by Nils Jonsson Everything else Copyright © CodeProject, 1999-2009 Web22 | Advertise on the Code Project |