Click here to Skip to main content
15,886,199 members
Articles / Programming Languages / C#
Article

MultiException: Type-Safe Collections without CollectionBase

Rate me:
Please Sign up or sign in to vote.
4.80/5 (4 votes)
12 Sep 20014 min read 65.5K   500   11   3
How to create Type-Safe collections without using CollectionBase

The Problem

I had been working on a base class for reading and writing to a database. I knew that when a new object (and hence record) was created there needed to be a mechanism for setting default values. I also knew that even with the default values there might not be enough information that the object could be saved.

For example: In a contact database, a new contact would by default have a blank name and blank phone number. Trying to save such a contact should not succeed and instead notify the user about the failure. Too many applications and web pages do this one failure at a time. I wanted to be able to cover all of the failures in one step.

This presents an interesting problem in any user interface. How can an object notify the environment about multiple failures? The standard way to notify the environment about any failure is to throw an exception. But I wanted to throw multiple exceptions and have them all be handled at one time. So was born the idea of a MultiException object.

Solution

The MultiException object should itself act as an Exception, but it should also act as a Collection. This way, when a save occurs, the data class has the ability to add exceptions to the MultiException and then throw the MultiException. The application can then catch the MultiException and enumerate all of the Exceptions displaying the reason for each one to the end user.

Implementation

The MultiException class turned out to be more of a chore then I originally thought. The easiest way to create a class that acts as a collection is to base it on the CollectionBase class. The problem with this approach was that I wanted MultiException to be based on ApplicationException and .Net only allows us one base class. .Net does, however, allow for a class to be based on one class and multiple interfaces.

MultiException was created based on ApplicationException but also implements IList. Being based on ApplicationException means that MultiException can be thrown as an exception. Implementing IList means that new exceptions can be added, gives us the ability to use indexes ( the [ ] operator ), and even allows us to use foreach loops!

Basing the class on ApplicationException was the easy part. Implementing IList was a bit more vague. It's not that implementing an interface is difficult, it's just that I didn't want to expose the IList interface. Why not, you ask? Because the IList interface is far too generic.

The IList interface includes methods like:

C#
public int Add(object O)

and

C#
public object this[int index]

Obviously we want to add Exceptions and Exceptions only, but the Add method of the IList interface accepts any old object. Sure we could test the object as it's passed in and throw an ArgumentException, but it just doesn't look nice and moreover doesn't enforce type-safety.

The obvious answer is to type our Add method correctly:

C#
public int Add(Exception E)

But the compiler will balk at you twice for this move! It will tell you first that the Add method of IList isn't implemented and second that the closest match doesn't have the right arguments.

What about making the generic version private? Nope, no good there. The compiler won't accept it as private either which is rightly so. How would anything access the method if we cast our object as an IList?

So then how do we do this right? It actually took me quite a while to find this one (it's easy to overlook). The trick is that you prefix the name of the interface to the generic version, and you make your type-safe version public. Example:

C#
int IList.Add(object O)         // Private Version
public int Add(Exception E)    // Public Version

Notice how you don't even mark the prefixed version public or private. C# understands that the prefixed version is there only to suffice the interface which makes this method operate in a special way. The prefixed version is used while the object is cast as an IList, but isn't even available while the object is a standard MultiException.

Conclusion

I use MultiException any time I have more then one error to report, and hiding implementation members is a hard-to-find trick. I hope you'll be able to use both in your future projects.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
United States United States
I live in Houston Texas and coding is my hobby. I am happily employed with a well-known computer software company.

My web address is: http://www.bienz.com and my e-mail is jared@bienz.com.

Comments and Discussions

 
Generalusing the new keyword Pin
Member 3202229-Mar-04 4:15
Member 3202229-Mar-04 4:15 
Generalprivate instance of IList member Pin
Taxo29-Jul-02 6:54
Taxo29-Jul-02 6:54 
GeneralRe: private instance of IList member Pin
Jared Bienz18-Sep-02 5:04
Jared Bienz18-Sep-02 5:04 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.