Upgrading to .NET 2.0? PowerCollections to your Aid.

September 1, 2007

no comments

The .NET 2.0 framework has been here a while, but if you’re like my team, you’re still using a lot of code that you wrote back at the .NET 1.1 days. It’s likely that many of these methods are using non-generic collections. This poses an annoying issue. Check out this method:

public IList GetAllUsers(IList userCodes) { IList list = new ArrayList(); //Add the users here... //... return list; }

On the one hand, you don’t want to touch the older code. It is working, it doesn’t have unit-tests, and anyway – It is just not feasible to go and change all your older code to use generics. The method might be even in a closed DLLs that you can’t change.

Still, you are now writing new code, and you want to use the old methods. Now, you don’t intend to write new .NET 2.0 code with non-generic collections, are you? So what are you going to do? Well, this:

private void PrintSomeUsers() { List<int> userCodes = new List<int>(); userCodes.Add(1); userCodes.Add(2); IList<User> users = Algorithms.TypedAs<User>(GetAllUsers(userCodes)); Console.WriteLine(Algorithms.ToString(users)); }

OK, so what do we have here? First, we are instantiating our generic list, and adding some numbers to it. Next, we are calling the GetAllUsers method. We can just past it the userCodes list, as List<T> thankfully implements the non-generic IList. Now, the magic happens when we call Algorithms.TypedAs<User>. This method belongs to the very useful PowerCollections library. It wraps our non generic collection, that was returned from GetAllUsers, with a generic coat. This prevents the need to copy the IList into an IList<T>, as some people might do, and therefore it is a lot more efficient, and elegant. Our next use of the Algorithms class is the ToString method, which simply creates a string representation of a collection. Note that overloads of Algorithms.TypedAs exist for ICollection<T>,IEnumerable<T> as well (they return ICollection and IEnumerable, respectively);

This is all nice and dandy, but in our case, GetAllUsers would have looked like this:

public ArrayList GetAllUsers(ArrayList userCodes) { ArrayList list = new ArrayList(); //Add the users here... //... return list; }

The idea of using Interfaces in method signatures seemed to escape us back than, and now the bad practice came back to bite us. List<T> does not have a cast to ArrayList, and in this case, we would have to change the userCodes parameter to use IList instead of ArrayList. Thankfully, it is usually trivial to do, since they are rather similar in nature.

Another complication might be if the PrintSomeUsers method accepted the userCodes as an IList<T> parameter.

private void PrintSomeUsers(IList<int> userCodes)

In this case, passing userCodes to GetAllUsers would fail, as IList<T> does not “inherit” from IList. And we already learned that it would be bad practice to accept the concrete List<T> as a parameter. In this case, we could use the Algorithms.Untyped method, like this:

private void PrintSomeUsers(IList<int> userCodes) { IList<User> users = Algorithms.TypedAs<User>( GetAllUsers(Algorithms.Untyped(userCodes)) ); Console.WriteLine(Algorithms.ToString(users)); }

Algorithms.Untyped does the exact opposite of TypedAs, by converting an IList<T> to an IList by means of a wrapper. Indeed, this is not the prettiest code in the world. In many cases, you should consider changing old methods to use generics entirely, but sometimes it is not a penalty you can afford. In these cases, Algorithms.TypedAs and Algorithms.Untyped can be very good friends to have around. Just remember to remove the wrappings once you do get around to refactoring the legacy code.

Add comment
facebook linkedin twitter email

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>