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:
- 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. - 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.
- Start Microsoft Visual Studio .NET or Microsoft Visual Studio 2005.
- On the File menu, point to New, and then click Project.
- 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. - In Solution Explorer, right-click Module1.vb, click Rename, and then type Host.vb.
- 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
- On the Project menu, click Add Class.
- 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. - 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
- 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