Comparing Objects using IComparable

I created a class which implemented “IComparable” for comparing “Players”. In my code I am comparing 2 players, but I’m not hitting a breakpoint on my “CompareTo()” method in the Player class. Here is a summary of the class:

  [Serializable()]
  public class Player : BaseSheet, IComparable
  {
    /// <summary>
    /// This method allows us to check the equality of two players.  If they are equal the method will return a zero.  The greater
    /// than or less than have no relevance for a Player object
    /// </summary>
    /// <param name="obj"></param>
    /// <returns></returns>
    public int CompareTo(object obj)
    {
      Player passedPlayer = (Player)obj;

      if (this.PlayerID == passedPlayer.PlayerID)
      {
        return 0;
      }
      else if (this.PlayerID > passedPlayer.PlayerID)
      {
        return 1;
      }
      else
      {
        return 0;
      }
    }
}

And the code which should trigger the comparison:


      foreach (FOOCheatSheetItem currentUserSheetItem in this.UserSheetItems)
      {
        // make sure each player sheet is ranked by CSWR
        FOOSupplementalSheetItem cswrSportsItem = this.CSWRSuppSheetItems.Find(delegate(FOOSupplementalSheetItem targetItem) { return (currentUserSheetItem.Player == targetItem.Player); });
      }

Well… because you are not calling CompareTo, you can override EqualTo (maybe it is Equal or Equals) as well, which would then invoke your method, or you can change your code.


      foreach (FOOCheatSheetItem currentUserSheetItem in this.UserSheetItems)
      {
        // make sure each player sheet is ranked by CSWR    
        FOOSupplementalSheetItem cswrSportsItem = this.CSWRSuppSheetItems.Find(delegate(FOOSupplementalSheetItem targetItem) { return (currentUserSheetItem.Player.CompareTo(targetItem.Player) == 0); });
      }

Thanks, I got things working by overriding the Equals(object) method. So does something else need to happen in order to compare using “==” vs the “CompareTo” method?

Nope. That should be it. You may need to have a GetHash() property in your class for the override to work, but it should “just work” if I remember correctly (I’ve only overrode those methods a handful of times over the past 7 years, so I might not be catching everything).

Yup, if you implement IComparable you should override Equals. IIRC when you touch any of that stuff you should also override GetHashCode() – see http://msdn.microsoft.com/en-us/library/ms173147(v=vs.80).aspx. In general I’d recommend paying close attention to the documentation when mucking about that deep in the System.Object() as there are lots of behavioral presumptions you are coming up against.

Personally, I’m not a huge fan of mucking with equality like that as it can be a bit of a landmine when you have to revisit the codebase for some reason or another. If we were doing custom list comparisons, we found it a bit saner to implement IComparer<T> rather than IComparable<T>.

A few notes too about the differences between IComparable<T> and IEquatable<T>…

IEquatable tests whether two objects are equal while IComparable reports a comparative state. For example, IEquatable would report that 3 is not equal to 5, but not thier relationship. IComparable would report that 3 is less than 5. So, depending on you needs and usage, you may want to expand your inheritance.

Great input, thanks.