Click here to Skip to main content
15,891,136 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I was looking at IComparer(Of T)[^] when I found:
"We recommend that you derive from the Comparer(Of T) class instead of implementing the IComparer(Of T) interface, because the Comparer(Of T) class provides an explicit interface implementation of the IComparer.Compare method and the Default property that gets the default comparer for the object."

Something similar is recommended for IEqualityComparer(Of T)[^].

Now my question is: Why should I derive rather than Implement?
I do not find the MSDN articles clear enough at this point.
Maybe someone could enlighten me? :)

Edit:
I have currently implemented my IComparer like this:
VB
Public Class OrderPriceComparer
    Implements IComparer(Of IOrder)

    Public Function Compare(ByVal x As IOrder, ByVal y As IOrder) As Integer Implements System.Collections.Generic.IComparer(Of IOrder).Compare
        Dim greater As Integer
        If x.CalculatePrice < y.CalculatePrice Then
            ' Y is greater.
            greater = -1
        ElseIf x.CalculatePrice = y.CalculatePrice Then
            ' Both are equal.
            greater = 0
        Else
            ' X is greater
            greater = 1
        End If

        Return greater
    End Function
End Class

It gets called like:
VB
' Orders is a list of orders that needs to be sorted by price.
Me.Orders.Sort(New OrderPriceComparer)

For a default ordering of my orders I have my OrderClass which Implements IComparable(Of IOrder).
The implementation looks like this:
VB
Public Function CompareTo(ByVal other As IOrder) As Integer Implements System.IComparable(Of IOrder).CompareTo
        Dim greater As Integer
        If other.ID > Me.ID Then
            ' Other is greater.
            greater = -1
        ElseIf other.ID = Me.ID Then
            ' This is just plain wrong, an ID is supposed to be unique!
            Throw New Exception("An order cannot be compared to itself.")
        Else
            ' This one is smaller
            greater = 1
        End If

        Return greater
    End Function

So I can now also call List(Of IOrder).Sort or pass it an optional IComparer to sort on anything different than ID.
Although I do have to make a new Class for every Property I want to sort on.

PS. I could not simply return the difference between x.CalculatePrice and y.CalculatePrice or Me.ID and other.ID because they are not Integers and I want to be safe for rounding differences and OutOfRangeException ;)
Posted
Updated 12-Apr-11 7:34am
v3

The only thing I can think of is that by inheriting from Comparer requires less work on your part because all of the required methods are already written for you, and you can override the ones you want. When you Implement an interface (in this case, IComparer), you MUST provide your own version of each method defined in the interface.

BTW, here's a tip/trick I submitted that does exactly what you're trying to do, and even supports comparing multiple properties within the object.

A Generic Comparison Class for Collection Items[^]
 
Share this answer
 
v2
Comments
Sergey Alexandrovich Kryukov 11-Apr-11 16:15pm    
I agree with you, my 5. There are some delicate items many developers miss, so why repeating all the same mistakes? But implementing from scratch is nothing like a big problem.
--SA
Sander Rossel 12-Apr-11 13:08pm    
Actually, Compare is a MustOverride Method, and thus does not leave the programmer with less work. It is also the only method in the Interface. The Comparer BaseClass does have an extra Equals function and Default Property though.
Very nice tip/trick you posted. Big 5 for that! I am going to put that in my application for sure :)
This is only a recommendation. The explanation on the page you references is clear to me. The class Comparer<T> is provided for your convenience and ease of implementation, not for limiting your freedom. You simply has less trouble, even though your own implementation of the interface from scratch would not be a great problem at all.

Do you see the case when your implementation of the interface from scratch is better? (In this case I would like to see your sample code and your explanation.) If you're sure you do — do it!

—SA
 
Share this answer
 
v2
Comments
Sander Rossel 12-Apr-11 13:35pm    
I have updated my question with code. Maybe I am thinking wrong in that IComparable provides a default sorting?
Sergey Alexandrovich Kryukov 12-Apr-11 15:05pm    
No, this is just the interface, cannot provide any code. Comparer does the implementation and the way to customize it -- Default property is important. As I already say, you're perfectly free to write the implementation of this interface if you can get any benefits out of it. Comparer just makes it easier and protect from some bugs.
--SA
Sander Rossel 12-Apr-11 15:24pm    
Well, since I am not doing anything really out of the ordinary I guess I could derive from the BaseClass and use my OrderClass with SortedList etc. Thanks for the explanations :)
Sergey Alexandrovich Kryukov 12-Apr-11 16:20pm    
That would be my guess...
Thanks for accepting this Answer and good luck.
Call again,
--SA
[Adding to what John and SA said]

The big thing they mention is that they implement the static Default property for you. The advantage there's that only one instance of the comparer is created for a specific type. And there are several other classes in the base class library that simply use Comparer<T>.Default, so by deriving from Comparer<> you get those classes to be able to use your derived class too (which may or may not be what you want).
 
Share this answer
 
v3
Comments
Sergey Alexandrovich Kryukov 11-Apr-11 21:03pm    
Correct, this is an important note. My 5. It is actually explained in the document referenced by OP, that's why I though OP already read that.
--SA
Sander Rossel 12-Apr-11 13:39pm    
Thanks. That is another clear answer. The Comparer(Of T) Class provides some extra functionality too (Equals). Could you name a few Classes that make use of this BaseClass rather than the Interface? I never can seem to find which Classes depend upon a specific Class. Only on which Classes a Class depends.
Nish Nishant 12-Apr-11 14:45pm    
Examples would be SortedSet<> and SortedList<> both of which uses Comparer<>.Default.
Sander Rossel 12-Apr-11 15:17pm    
Thanks, I might just use the BaseClass then :)

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900