How to use the IComparable and the IComparer interfaces in Visual Basic .NET or in Visual Basic 2005 (321292)



The information in this article applies to:

  • Microsoft Visual Basic .NET (2002)
  • Microsoft Visual Basic .NET (2003)
  • Microsoft Visual Basic 2005

This article was previously published under Q321292
This article refers to the following Microsoft .NET Framework Class Library namespace:
  • System.Collections

IN THIS TASK

SUMMARY

This step-by-step article demonstrates how to use two interfaces: IComparer and IComparable. These interfaces are addressed in the same article for two reasons:
  • These interfaces are frequently used together.
  • Although the interfaces are similar (and have similar names), the purposes that they serve are a little different.
If you have an array of types (such as the string or the integer types) that already support IComparer, you can sort that array without providing any explicit reference to IComparer. In this case, the elements of the array are cast to the default implementation of IComparer (Comparer.Default) for you. However, if want to sort and to compare your custom objects, you must implement either or both of these interfaces.

back to the top

IComparable Interface

The IComparable interface provides a method to compare two objects of a particular type. Use this interface if you want to order your object.

Think of IComparable as providing a default sort order for your objects. For example, if you have an array of objects of your type, and if you call the Sort method on that array, you can use the IComparable interface to compare the objects during the sort. When you implement the IComparable interface, you must also implement the CompareTo method. For example:
Function CompareTo(ByVal obj As Object) As Integer Implements IComparable.CompareTo
   Dim c As car = CType(obj, car)
   Return String.Compare(Me.mmake, c.mmake)
End Function
				
The comparison in the method differs depending on the data type of the value that is being compared. This example uses the String.Compare method because the property that is being compared is a string.

back to the top

IComparer Interface

The IComparer interface provides additional comparison mechanisms. For example, you may want to order your class on several fields or properties, by ascending and descending order on the same field, or both.

To use IComparer, follow these steps:
  1. Declare a class that implements IComparer, and implement the Compare method. For example:
    Private Class sortYearDescendingHelper : Implements IComparer
       Function Compare(ByVal a As Object, ByVal b As Object) As Integer Implements IComparer.Compare
          Dim c1 As car = CType(a, car)
          Dim c2 As car = CType(b, car)
    
          If (c1.year < c2.year) Then
             Return 1
          End If
    
          If (c1.Year > c2.Year) Then
             Return -1
          Else
             Return 0
          End If
       End Function
    End Class
    						
    Notice that the IComparer.Compare method requires a tertiary comparison. 1, 0, or -1 is returned, depending on whether one value is greater than, equal to, or less than the other.

    NOTE: You can change the sort order (ascending versus descending) by switching the logical operators in this method.
  2. Declare a method that returns an instance of your IComparer object. This example uses the object as the second argument when you call the overloaded Array.Sort method that accepts IComparer.
    Public Shared Function sortYearAscending() As IComparer
       Return CType(New sortYearAscendingHelper(), IComparer)
    End Function
    					
The use of IComparer is not limited to arrays, it is accepted as an argument in a number of different collection and control classes.

back to the top

Step-by-Step Example

The example in this section demonstrates how to use IComparer and IComparable. This example creates a class named car. The car object has the two properties: make and year. This example uses the IComparable interface to sort on the make field in ascending order. This example then uses the IComparer interface to sort on the make field in descending order. This example also provides ascending and descending sorts for the year property through the use of IComparer.
  1. Start Microsoft Visual Studio .NET or Microsoft Visual Studio 2005.
  2. On the File menu, point to New, and then click Project.
  3. Click Visual Basic Projects under Project Types, click Console Application under Templates, and then type ConsoleEnum in the Name box.

    Note In Visual Basic 2005, click Visual Basic under Project Types.
  4. In Solution Explorer, right-click Module1.vb, click Rename, and then type Host.vb.
  5. Replace the code in Host.vb with the following code:
    Module Module1
    
       Sub Main()
          Dim c As car
          Dim arrayOfCars() As car = _
             { _
             New car("Ford", 1992), _
             New car("Fiat", 1988), _
             New car("Buick", 1932), _
             New car("Ford", 1932), _
             New car("Dodge", 1999), _
             New car("Honda", 1977) _
             }
    
          Dim t As String = vbTab & vbTab
          Dim n As String = vbCrLf
    
          Console.WriteLine("Array - Unsorted" & n)
          For Each c In arrayOfCars
             Console.WriteLine(c.Make & t & c.Year)
          Next
          Array.Sort(arrayOfCars)
          Console.WriteLine(n & "Array - Sorted by Make (Ascending - IComparable)" & n)
          For Each c In arrayOfCars
             Console.WriteLine(c.Make & t & c.Year)
          Next
          Array.Sort(arrayOfCars, car.sortYearAscending())
          Console.WriteLine(n & "Array - Sorted by Year (Ascending - IComparer)" & n)
          For Each c In arrayOfCars
             Console.WriteLine(c.Make & t & c.Year)
          Next
    
          Array.Sort(arrayOfCars, car.sortMakeDescending())
          Console.WriteLine(n & "Array - Sorted by Make (Descending - IComparer)" & n)
          For Each c In arrayOfCars
             Console.WriteLine(c.Make & t & c.Year)
          Next
    
          Array.Sort(arrayOfCars, car.sortYearDescending())
          Console.WriteLine(n & "Array - Sorted by Year (Descending - IComparer)" & n)
          For Each c In arrayOfCars
             Console.WriteLine(c.Make & t & c.Year)
          Next
    
          Console.ReadLine()
    
       End Sub
    End Module
    					
  6. On the Project menu, click Add Class.
  7. In the Add New Item dialog box, type car in the Name box, and then click Open.

    Note In Visual Studio 2005, click Add instead of Open.
  8. Replace the code in car.vb with the following code:
    Option Explicit On 
    Option Strict On
    
    Imports System.Collections
    
    Public Class car : Implements IComparable
       ' Nested classes to do secondary sorts
       Private Class sortYearAscendingHelper : Implements IComparer
          Function Compare(ByVal a As Object, ByVal b As Object) As Integer Implements IComparer.Compare
             Dim c1 As car = CType(a, car)
             Dim c2 As car = CType(b, car)
    
             If (c1.year > c2.year) Then
                Return 1
             End If
    
             If (c1.Year < c2.Year) Then
                Return -1
             Else
                Return 0
             End If
          End Function
       End Class
    
       Private Class sortYearDescendingHelper : Implements IComparer
          Function Compare(ByVal a As Object, ByVal b As Object) As Integer Implements IComparer.Compare
             Dim c1 As car = CType(a, car)
             Dim c2 As car = CType(b, car)
    
             If (c1.year < c2.year) Then
                Return 1
             End If
    
             If (c1.Year > c2.Year) Then
                Return -1
             Else
                Return 0
             End If
          End Function
       End Class
    
       Private Class sortMakeDescendingHelper : Implements IComparer
          Function Compare(ByVal a As Object, ByVal b As Object) As Integer Implements IComparer.Compare
             Dim c1 As car = CType(a, car)
             Dim c2 As car = CType(b, car)
    
             Return String.Compare(c2.Make, c1.Make)
          End Function
       End Class
       ' End nested classes.
    
       Private myear As Integer
       Private mmake As String
    
       Public Sub New(ByVal Make As String, ByVal Year As Integer)
          mmake = Make
          myear = Year
       End Sub
    
       Public Property Year() As Integer
          Get
             Return myear
          End Get
    
          Set(ByVal Value As Integer)
             myear = Value
          End Set
       End Property
    
       Public Property Make() As String
          Get
             Return mmake
          End Get
      
          Set(ByVal Value As String)
             mmake = Value
          End Set
        End Property
    
        Function CompareTo(ByVal obj As Object) As Integer Implements IComparable.CompareTo
           Dim c As car = CType(obj, car)
    
           Return String.Compare(Me.mmake, c.mmake)
        End Function
    
        Public Shared Function sortYearAscending() As IComparer
           Return CType(New sortYearAscendingHelper(), IComparer)
        End Function
    
        Public Shared Function sortYearDescending() As IComparer
           Return CType(New sortYearDescendingHelper(), IComparer)
        End Function
    
        Public Shared Function sortMakeDescending() As IComparer
           Return CType(New sortMakeDescendingHelper(), IComparer)
        End Function
    End Class
    					
  9. Run the project. Notice that the following output appears in the Console window:

    Array - Unsorted
    
    Ford            1992
    Fiat            1988
    Buick           1932
    Ford            1932
    Dodge           1999
    Honda           1977
    
    Array - Sorted by Make (Ascending - IComparable)
    
    Buick           1932
    Dodge           1999
    Fiat            1988
    Ford            1932
    Ford            1992
    Honda           1977
    
    Array - Sorted by Year (Ascending - IComparer)
    
    Ford            1932
    Buick           1932
    Honda           1977
    Fiat            1988
    Ford            1992
    Dodge           1999
    
    Array - Sorted by Make (Descending - IComparer)
    
    Honda           1977
    Ford            1932
    Ford            1992
    Fiat            1988
    Dodge           1999
    Buick           1932
    
    Array - Sorted by Year (Descending - IComparer)
    
    Dodge           1999
    Ford            1992
    Fiat            1988
    Honda           1977
    Buick           1932
    Ford            1932
    						

back to the top

Modification Type:MinorLast Reviewed:10/3/2006
Keywords:kbvs2005applies kbvs2005swept kbHOWTOmaster KB321292 kbAudDeveloper