Login | Register   
LinkedIn
Google+
Twitter
RSS Feed
Download our iPhone app
TODAY'S HEADLINES  |   ARTICLE ARCHIVE  |   FORUMS  |   TIP BANK
Browse DevX
Sign up for e-mail newsletters from DevX


advertisement
 

Comparing Things


advertisement
ne thing I'm pretty sure of is that boys like to compare things. Yes, I know what you're thinking—that's not where I'm going here. I have a vivid recollection of a time a few years back when I tipped the scales at a good 20 percent more than I currently do. I remember shopping in a grocery store for some snacks with pals Brian Randell and Andy Baron. Andy (who is also svelter now than he was then) and I were both kvetching about the sizes of our, um, rears. I was sure that mine was larger but Andy wasn't convinced. Right there in the grocery store I coerced Brian to act as judge. (I've spared you the photo. I figured your imagination was creative enough in this particular scenario.) I won, of course. I've always won this contest. I believe I always will.

Flash forward a few years. It's PDC time in 2003, and a bunch of my geek pals are staying at my house in the hills of Los Angeles. Andy was there again, but for this event we added iron-man Australian Adam Cogan and "I've ridden my bike across the country" Oregonite Tom Howe. We had been biking up the hill my house is built upon (see the previous two issues of CoDe Magazine for more biking stories) and Adam had made his way up with nary a huff nor a puff, even though it's a steep ride. We figured he had to have the largest thighs in the group. So, again, we started measuring. This particular body part turns out to be harder to measure via mere visual inspection. What we needed was some algorithm for comparing the actual "thighage," so we could sort ourselves accordingly. Pragmatic Mary Chipman suggested that we use a measuring tape. Of course, I don't own one so we substituted dental floss. (Don't you wish you had been there?) Adam won this contest, although barely.

The segue to real content comes unusually early this month, because I have this feeling that I've described comparing body parts just about enough. Of course, comparing and sorting are a critical part of working with the .NET Framework. Actually, it's hard to imagine getting much computing work done without sorting and comparing, and I love the way the .NET Framework handles these tasks. Arrays, collection classes, and any other data structure in which you might want to put ordered data all provide a Sort method that takes care of the mundane sorting details. Unless you have some specific needs, you shouldn't need to create your own sorting procedure ever again. You may need to assist the .NET Framework in comparing and ordering your data, however.

If you've created a simple ArrayList instance, for example, and you add four items to it, you can easily sort and display the results. The following code demonstrates how this works:

Dim al As New ArrayList al.Add("Ken") al.Add("Tom") al.Add("Andy") al.Add("Adam") al.Sort() For Each name As String In al Debug.WriteLine(name) Next


When you sort a collection of any type of object, the Sort method needs some way to compare any two instances of the type. In order to generalize this comparison behavior, the .NET Framework provides a default compare method for each type that it may need to sort. Calling the Sort method of the ArrayList class uses the default "comparer" for each element in the data structure in order to determine the correct ordering. Because each element is a string, and the String class provides a mechanism for comparing one string to another, this all works transparently. If you read the documentation for the String class (or any other simple class built into the .NET Framework) you'll find that the String class implements the IComparable interface, and by doing so, it provides a CompareTo method that implements the single required member of the IComparable interface.

If you read the documentation for the IComparable interface, you'll learn that this interface requires implementers to provide a method (normally named CompareTo) that accepts an object and returns an integer. The goal of this procedure is to compare the instance of the object whose CompareTo method you called with the object passed to the procedure. If the two objects have the same value (and it's up to the developer of the class to determine what the "value" of the object is), the procedure should return zero (0). If the current instance value is less than the passed-in object, the method will return a negative value; if greater, the method will return a positive value.

For built-in classes that implement IComparable, you don't have to do anything if you want to use the default sort order. But what if you want to sort instances of your own class? You can provide a default sort capability for your class by implementing the IComparable interface yourself. Say, for example, you've created a BigBoy class to track thigh size. If you want to be able to sort a collection of BigBoy objects, you'll need to implement IComparable. The following example includes code that allows you to compare two BigBoy instances, and thereby, sort a collection of these objects:

Public Class BigBoy Implements IComparable Public Name As String Public ThighSize As Integer Public Sub New( _ ByVal Name As String, _ ByVal Size As Integer) Me.Name = Name Me.ThighSize = Size End Sub Public Overrides Function ToString() _ As String Return String.Format( _ "{0} has {1} inch thighs.", _ Me.Name, Me.ThighSize) End Function Function CompareTo( _ ByVal obj As Object) As Integer _ Implements IComparable.CompareTo Dim other As BigBoy other = CType(obj, BigBoy) Return Me.Name.CompareTo(other.Name) End Function End Class


The CompareTo method in BigBoy, which compares two instances of the type, uses the CompareTo method of the String class to compare the two names. What if you wanted to sort on thigh size instead? No problem—just modify the line of code that performs the comparison:


Return Me.ThighSize. _ CompareTo(other.ThighSize)

It doesn't really matter how you perform this comparison, as long as your return value matches the requirements of the CompareTo method.

You might also want to change the default sort behavior for a built-in type, or provide multiple sort orderings for your own class. For example, what if you want to sort a collection of strings in reverse order? What if you want to be able to provide your list of BigBoy objects in either name or size order, depending on the circumstances? In that case, you'll need to provide yet another class—this time you need to implement the IComparer interface.

The Sort method of each collection type allows you to pass an instance of a class that implements IComparer in order to determine the compare order for the objects within the collection. The IComparer interface requires you to supply just a single procedure—Compare—to compare two objects that it receives as parameters.

For example, to sort strings in reverse order, you might create a class that implements IComparer like this:

Class StringReverseComparer Implements IComparer Public Function Compare( _ ByVal x As Object, _ ByVal y As Object) As Integer _ Implements System.Collections. _ IComparer.Compare Dim str1 As String = _ CType(x, String) Dim str2 As String = _ CType(y, String) Return -1 * x.CompareTo(y) End Function End Class

Then, when it comes time to sort the ArrayList of strings, you could revise the previous code so that it looks like this:

al.Sort(New StringReverseComparer())


The same concept applies to the BigBoy class. To create a comparison class that allows you to sort based on ThighSize, you could add this class to your project:

Class ThighComparer Implements IComparer Public Function Compare( _ ByVal x As Object, _ ByVal y As Object) As Integer _ Implements System.Collections. _ IComparer.Compare Dim bb1 As BigBoy = CType(x, BigBoy) Dim bb2 As BigBoy = CType(y, BigBoy) Return bb1.ThighSize. _ CompareTo(bb2.ThighSize) End Function End Class

Then, when it came time to sort the ArrayList, you could either sort using the default sort, al.Sort(), or you could sort using the new comparer:

al.Sort(New ThighComparer())

I clearly like to compare things, and this is just a clean and elegant solution to a common and basic programming problem. This is just about as simple a solution as they could have come up with. Using the IComparable and IComparer interfaces, you can create flexible applications that can work with data in any number of ways. And one thing's for sure: it's more practical than comparing using dental floss.



   
Ken Getz is a senior consultant with MCW Technologies and splits his time between programming, writing, and training. He specializes in tools and applications written in Visual Studio .NET and Visual Basic. Ken is the author of the highly rated .Finalize() column in CoDe Magazine. He is also the co-author of several best-selling books, including Access 2002 Developer's Handbooks with Paul Litwin and Mike Gunderloy, Visual Basic Language Developer's Handbook with Mike Gilbert, and VBA Developer's Handbook with Mike Gilbert (Sybex). He co-wrote several training courses for Application Developer's Training Company, including VB.NET, ASP.NET, Access 2000 and 97, Visual Basic 6, and Visual Basic 5 seminars. He has also recorded video training for AppDev covering VB.NET, ASP.NET, VB6, Access 2000, and Access 97. Ken is a frequent speaker at technical conferences and has spoken often at Microsoft's Tech-Ed conference. Ken's also a technical editor for Access-VB-SQL Advisor magazine and a columnist for Informant Publications' asp.netPRO magazine..
Comment and Contribute

 

 

 

 

 


(Maximum characters: 1200). You have 1200 characters left.

 

 

Sitemap
Thanks for your registration, follow us on our social networks to keep up-to-date