Article Options
Premium Sponsor
Premium Sponsor

 »  Home  »  .NET Newbie  »  OOP: Create, Collect, Sort, Save and Retrieve Objects  »  Sortable Objects - Sorting Players By Name or Score
 »  Home  »  Visual Studio 2005  »  OOP: Create, Collect, Sort, Save and Retrieve Objects  »  Sortable Objects - Sorting Players By Name or Score
 »  Home  »  Windows Development  »  Visual Basic 2005  »  OOP: Create, Collect, Sort, Save and Retrieve Objects  »  Sortable Objects - Sorting Players By Name or Score
OOP: Create, Collect, Sort, Save and Retrieve Objects
by Ged Mead | Published  03/18/2007 | .NET Newbie Visual Studio 2005 Visual Basic 2005 | Rating:
Sortable Objects - Sorting Players By Name or Score

  IComparer

   Now we have a basic class and a simple collection utility in which we can store Person objects, we can turn our attention to improving the code so that Players can be easily sorted into the correct order.   But what exactly is the "correct" order of Player objects?  The VB.NET compiler certainly can't answer that question for you; the Player Class is your invention and the compiler only knows the details that you tell it.

   So, as a useful exercise for future applications, I am going to say that at times we might want the Players sorted by Name and at other times we may want them sorted by their Score.    So essentially we want to have access to multiple versions of some device that will help us sort the Players.   And of course such a device does indeed exist - and it's the IComparer Interface.

  In its most simple terms an IComparer Interface is a skeleton on which you can add flesh to the bones.   It knows how to sort (something that is quite a complex set of processes, as you'll know if you've ever attempted it yourself), but needs to know what it is being asked to sort.   

   To take a non-technical example, consider a new employee in a factory.    The new worker will understand the general principle of sorting - something is placed in a set position in an order of items.    If the worker was sent to a storehouse where there was a jumbled stack of boxes and told to "sort" them, he would have several options of how the sort should be implemented:  by size, by weight, by the contents name, by the color of the box, by serial number, etc.    In real life he would need to be told by the supervisor what sort order is required and then he would be able to get on with the job.

  And that's quite a reasonable analogy for what IComparer does.  It knows how to sort in general, but needs to be told the specifics.  Let's now look at how you use IComparer.

Sorting by Player.Name

   Amend the Player Class by adding the following lines at the end of the Class code (That is, right above the line that reads "End Class"):

Public Class CompareByNameOfPlayer
   Implements IComparer(of Player)

   Now press the Enter key and two things will happen:  The wavy blue line under the word IComparer will disappear and the outline of a new procedure will be automatically inserted into this new class.  (If necessary, also type in "End Class" to remove any remaining error message.)   The outline should look like this:

Public Function Compare(ByVal x As Player, ByVal y As Player) As Integer Implements System.Collections.Generic.IComparer(Of Player).Compare

End Function

      One of the useful features of using the Generics version of IComparer is that this Compare function knows that the comparison will be based on Player objects and so it uses the Player Type in the parameters shown there - x and y.   In the non-generics version, this would be of type Object and we would need to write more code in the function to cast from Object to Player before we could safely deal with it.  

    We will need to add some code to this skeleton procedure to give instructions on how we want it to sort. 

If x Is Nothing AndAlso y Is Nothing Then Return 0

If x Is Nothing And Not y Is Nothing Then Return 1

If Not x Is Nothing And y Is Nothing Then Return -1

Return String.Compare(x.Name, y.Name, True)

   These four lines are all that are needed to implement a valid Compare method that can be used by the compiler to sort collections of Player objects.   As you can see, the first three lines deal with cases where either or both the parameters are Nothing.     I'm not entirely convinced if these are necessary, bearing in mind that we have restricted our code to a strongly typed collection of Player objects, but it's habit I've got into pre-VB 2005 and it won't do any harm even if it does no good!

   The actual comparison of Names takes place in the last line.  Because we are dealing with a String (the Name Property is of type String) we can simply harness the String.Compare function and use this to compare two Names.  String.Compare will carry out the comparison for us  because it knows how to compare Strings alphabetically.   As you will see when we move on to the sort by Score procedure, we have to take a slightly longer way round.

   I have also included an additional parameter,  the IgnoreCase Boolean parameter which I have set to True.   This ensures that the comparisons will be made in a case insensitive manner - an approach that makes sense in this particular scenario.

   You can now try out this comparer and use it to sort the List of Players.   Put this code in the Windows Form:

PlayersList.Sort(New Player.CompareByNameOfPlayer) 
  
ListBox1.Items.Clear()
      For Each APlayer As Player In PlayersList
         ListBox1.Items.Add(String.Format("{0}, Current Score: {1}", APlayer.Name, APlayer.Score.ToString))
       Next

  Enter a few names and then click the button.  If all is well, the sorted Players List will appear.   You can add further names and click the button again to update the sort.   If your version isn't working as it should, check out the demo solution included with this article.

Sorting by Player.Score

  As I mentioned earlier, the procedure for creating a comparer to allow comparisons and sorting by the Players' Scores is similar.   Once again we will create a nested Class:

Public Class CompareByScore
Implements IComparer(Of Player)

Public Function Compare(ByVal x As Player, ByVal y As Player) As Integer _
Implements IComparer(Of Player).Compare

   If x Is Nothing AndAlso y Is Nothing Then Return 0
   If x Is Nothing And Not y Is Nothing Then Return 1
   If Not x Is Nothing And y Is Nothing Then Return -1
   If x.Score < y.Score Then
    Return -1
   ElseIf x.Score = y.Score Then
    Return 0
   Else
    Return 1
   End If
End Function
End Class

 This code is quite similar to the code we used for sorting by name, the difference being that we can't use the String.Compare method here because we are dealing with an Integer and not a String.    So you will see that last few lines of code manually compare the two values and return -1, 0 or 1 depending on which argument has the higher value.

   For testing purposes at this point you could add a second button to the form and put code in its Click event similar to the code we used in the last section when sorting by Name. i.e.

PlayersList.Sort(New Player.CompareByScore) 
  
ListBox1.Items.Clear()
      For Each APlayer As Player In PlayersList
         ListBox1.Items.Add(String.Format("{0}, Current Score: {1}", APlayer.Name, APlayer.Score.ToString))
       Next

   I have highlighted the only change that you need to make to call this variation of the sort.

   In reality, you probably won't want a separate button for each kind of sort and it's very common to use a set of Radio Buttons to allow a user to select one setting from a choice of two or more mutually exclusive options.  I won't delve into that here, but you can see a sample in the demo Solution that is included with this article.

Summary (So Far)

  So by this stage we have seen how to create a simple class that will allow us to build objects.  We saw how to create collections of those objects and here we have discussed how to sort those collections in various ways.    None of the code is very complex and you can use the same steps to create classes and sortable collections of your own.

 

 

   

Sponsored Links