By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
457,728 Members | 1,150 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 457,728 IT Pros & Developers. It's quick & easy.

about IComparer and Comparer

P: n/a
Hello!

I'm reading in a book and this can't be correct it says.
"Objects passed to Comparer.Compare() are checked to see if they support
IComparable.
If they do, then that implementation is used"

Assume I have a collection of Item(s) in an ArrayList
This class called Item support the IComparable interface which contains the
CompareTo method
so this method is impemented in class Item.

Now I can sort in the way that this CompareTo is implemented.

Now assume I want to be able to sort the collection of item(s) in another
way then this CompareTo is implementet
so I create an helper class which implement the IComparer interface which
contains method Compare.

So not to my question when object of type Item is passed to the Compare
method that implementation
is used of course not the implementation that exist for the IComparable.

//Tony
Jun 27 '08 #1
Share this Question
Share on Google+
10 Replies


P: n/a
ArrayList.Sort has several overloads; the parameterless one uses
Comparer.Default, which (as you discussed) will use the objects
IComparable support (if any). If you want a custom sort, there is an
overload (2, actually) that accepts your custom IComparer, in which
case Comparer.Default is *not* used.

Note that in .NET 2.0, it would be better to consider List<T>,
IComparer<T>, IComparable<Tand Comparer<T>.Default.

Marc
Jun 27 '08 #2

P: n/a
On Jun 17, 9:18 am, "Tony" <johansson.anders...@telia.comwrote:
I'm reading in a book and this can't be correct it says.
"Objects passed to Comparer.Compare() are checked to see if they support
IComparable.
If they do, then that implementation is used"
One thing to note is that most of the time you should now be using the
generic Comparer<Tclass and in particular Comparer<T>.Default.
Assume I have a collection of Item(s) in an ArrayList
This class called Item support the IComparable interface which contains the
CompareTo method
so this method is impemented in class Item.

Now I can sort in the way that this CompareTo is implemented.

Now assume I want to be able to sort the collection of item(s) in another
way then this CompareTo is implementet
so I create an helper class which implement the IComparer interface which
contains method Compare.
So far so good - but at that point you don't use the Comparer class,
you just pass an instance of your IComparer implementation into
whatever sorting method you're using.
So not to my question when object of type Item is passed to the Compare
method that implementation
is used of course not the implementation that exist for the IComparable.
The quote you gave specified part of the implementation of
Comparer.Compare. If you're not calling Comparer.Compare, then the
quote is irrelevant. Why would you call Comparer.Compare if you want
to use a custom IComparer implementation?

Perhaps it would help if you'd provide a short but complete example,
and ask what the behaviour is and why for a specific method call.

Jon
Jun 27 '08 #3

P: n/a
Here I have not Complete program enough to be able to answer my question.
Here again I pass an object to this Comparer.Compare() although there is an
Default in between.
>Objects passed to Comparer.Compare() are checked to see if they support
IComparable.
If they do, then that implementation is used"
Below when I pass object to this Comparer.Default.Compare I don't use the
implementation from
IComparable that the text above is claiming I use whatever relevent code I
want.?

So what the text is claiming must be completely nonsens.!

public class Item : IComparable
{
private int steelGrade;
private int heatNumber;
private string mspName;
private string dateTime;
private int optTime;
private ArrayList listOpt;
private ArrayList listDateTime;

public ArrayList ListDateTime
{
set { listDateTime = value; }
get { return listDateTime; }
}

public ArrayList ListOpt
{
set {listOpt = value; }
get { return listOpt; }
}

public int OptTime
{
set { optTime = value; }
get { return optTime; }
}

public string DateTime
{
set { dateTime = value; }
get { return dateTime; }
}

public int Steelgrade
{
set { steelGrade = value; }
get { return steelGrade; }
}

public int HeatNumber
{
set { heatNumber = value; }
get { return heatNumber; }
}

public string MspName
{
set { mspName = value; }
get { return mspName; }
}

public int CompareTo(object right)
{
if (right is Item)
{
Item item = right as Item;
if (this.HeatNumber != item.HeatNumber)
return this.HeatNumber.CompareTo(item.HeatNumber);
else
return this.MspName.CompareTo(item.MspName);
}
else
throw new ArgumentException("Object to compare is not a Item
object");

}
}
public class ItemComparer : IComparer
{
public static IComparer Default = new ItemComparer();

public int Compare(object left, object right)
{
if (left is Item && right is Item)
{
if (((Item)left).Steelgrade != ((Item)right).Steelgrade)
return Comparer.Default.Compare(
((Item)left).Steelgrade, ((Item)right).Steelgrade);
else
return Comparer.Default.Compare(
((Item)left).MspName, ((Item)right).MspName);
}
else
throw new ArgumentException("One of the object is not an
Item");
}
}

//Tony
"Jon Skeet [C# MVP]" <sk***@pobox.comskrev i meddelandet
news:cc**********************************@27g2000h sf.googlegroups.com...
On Jun 17, 9:18 am, "Tony" <johansson.anders...@telia.comwrote:
I'm reading in a book and this can't be correct it says.
"Objects passed to Comparer.Compare() are checked to see if they support
IComparable.
If they do, then that implementation is used"

One thing to note is that most of the time you should now be using the
generic Comparer<Tclass and in particular Comparer<T>.Default.
Assume I have a collection of Item(s) in an ArrayList
This class called Item support the IComparable interface which contains
the
CompareTo method
so this method is impemented in class Item.

Now I can sort in the way that this CompareTo is implemented.

Now assume I want to be able to sort the collection of item(s) in
another
way then this CompareTo is implementet
so I create an helper class which implement the IComparer interface
which
contains method Compare.

So far so good - but at that point you don't use the Comparer class,
you just pass an instance of your IComparer implementation into
whatever sorting method you're using.
So not to my question when object of type Item is passed to the Compare
method that implementation
is used of course not the implementation that exist for the IComparable.

The quote you gave specified part of the implementation of
Comparer.Compare. If you're not calling Comparer.Compare, then the
quote is irrelevant. Why would you call Comparer.Compare if you want
to use a custom IComparer implementation?

Perhaps it would help if you'd provide a short but complete example,
and ask what the behaviour is and why for a specific method call.

Jon

Jun 27 '08 #4

P: n/a
That is *not* a complete program; it has no "Main", so does nothing
(not even compile...).

Re your question - the only things you pass to
Comparer.Default.Compare(...) are two ints (the two Steelgrade
properties); I fully expect that Comparer will give the correct answer
for comparing two ints, but there is no reason to expect it to call
your IComparable implementation - it isn't comparing Item, it is
comparing ints - it will use the Int32.Compare method.

Marc
Jun 27 '08 #5

P: n/a
(white lie - you also pass two strings, but this will behave similarly)
Jun 27 '08 #6

P: n/a
On Jun 17, 10:04 am, "Tony" <johansson.anders...@telia.comwrote:
Here I have not Complete program enough to be able to answer my question.
Here again I pass an object to this Comparer.Compare() although there is an
Default in between.
Well, your code is really making things confusing by having an
ItemComparer.Default as well as using Comparer.Default.
Objects passed to Comparer.Compare() are checked to see if they support
IComparable.
If they do, then that implementation is used"

Below when I pass object to this Comparer.Default.Compare I don't use the
implementation from
IComparable that the text above is claiming I use whatever relevent code I
want.?
The call to Comparer.Default.Compare with the two different Steelgrade
values will use the fact that int implements IComparable. That's all
that the text is claiming. The rest of your code isn't a call to
Comparer.Compare, it's an implementation of IComparer.Compare. There's
a huge difference.

Mind you, your code would be significantly simpler if you just called
Compare directly, preferrably avoiding all those casts:

public int Compare(object left, object right)
{
// TODO: optimise for left == right, and consider cases
// where one side or other is null
Item leftItem = left as Item;
Item rightItem = right as Item;
if (leftItem == null || rightItem == null)
{
throw new ArgumentException("One of the objects is not an
Item");
}
if (leftItem.Steelgrade != rightItem.Steelgrade)
{
return leftItem.Steelgrade.CompareTo(rightItem.Steelgrade );
}
// TODO: Consider what kind of string comparison you want (culture/
ordinal/case sensitive)
return leftItem.MspName.CompareTo(rightItem.MspName);
}
So what the text is claiming must be completely nonsens.!
No it's not. Comparer.Compare will use the IComparable.CompareTo
implementation. But other implementations of IComparer are free to do
what they want.

It seems to me that you're not distinguishing between the interface
(IComparer) and *one* implementation (Comparer).

Jon
Jun 27 '08 #7

P: n/a
Here's a Main that demonstrates it working just fine... you'll have to
forgive some C# 3 initializer syntax (easy enough to see what it does,
though):

class Program
{
static void Main()
{
ArrayList list = new ArrayList();
list.Add(new Item { HeatNumber = 1, Steelgrade = 4, MspName =
"def" });
list.Add(new Item { HeatNumber = 3, Steelgrade = 4, MspName =
"ghi" });
list.Add(new Item { HeatNumber = 1, Steelgrade = 2, MspName =
"abc" });
list.Add(new Item { HeatNumber = 2, Steelgrade = 1, MspName =
"jkl" });
Console.WriteLine("Using custom sort (HeatNumber, MspName)");
list.Sort();
foreach (Item item in list)
{
Console.WriteLine("{0}: hn: {1}, sg: {2}", item.MspName,
item.HeatNumber, item.Steelgrade);
}
Console.WriteLine("Using custom sort (Steelgrade, MspName)");
list.Sort(ItemComparer.Default);
foreach (Item item in list)
{
Console.WriteLine("{0}: hn: {1}, sg: {2}", item.MspName,
item.HeatNumber, item.Steelgrade);
}
}
}

Jun 27 '08 #8

P: n/a
(sorry, copy/paste - first is the default sort using the item's
IComparable implementation)
Jun 27 '08 #9

P: n/a
Hello!

You say that your code would be significantly simpler if you just called
Compare directly, preferrably avoiding all those casts:
You you mean as the code prove instead CompareTo(...) I assume

//Tony

"Jon Skeet [C# MVP]" <sk***@pobox.comskrev i meddelandet
news:80**********************************@s50g2000 hsb.googlegroups.com...
On Jun 17, 10:04 am, "Tony" <johansson.anders...@telia.comwrote:
Here I have not Complete program enough to be able to answer my
question.
Here again I pass an object to this Comparer.Compare() although there is
an
Default in between.

Well, your code is really making things confusing by having an
ItemComparer.Default as well as using Comparer.Default.
>Objects passed to Comparer.Compare() are checked to see if they
support
IComparable.
If they do, then that implementation is used"
Below when I pass object to this Comparer.Default.Compare I don't use
the
implementation from
IComparable that the text above is claiming I use whatever relevent code
I
want.?

The call to Comparer.Default.Compare with the two different Steelgrade
values will use the fact that int implements IComparable. That's all
that the text is claiming. The rest of your code isn't a call to
Comparer.Compare, it's an implementation of IComparer.Compare. There's
a huge difference.

Mind you, your code would be significantly simpler if you just called
Compare directly, preferrably avoiding all those casts:

public int Compare(object left, object right)
{
// TODO: optimise for left == right, and consider cases
// where one side or other is null
Item leftItem = left as Item;
Item rightItem = right as Item;
if (leftItem == null || rightItem == null)
{
throw new ArgumentException("One of the objects is not an
Item");
}
if (leftItem.Steelgrade != rightItem.Steelgrade)
{
return leftItem.Steelgrade.CompareTo(rightItem.Steelgrade );
}
// TODO: Consider what kind of string comparison you want (culture/
ordinal/case sensitive)
return leftItem.MspName.CompareTo(rightItem.MspName);
}
So what the text is claiming must be completely nonsens.!

No it's not. Comparer.Compare will use the IComparable.CompareTo
implementation. But other implementations of IComparer are free to do
what they want.

It seems to me that you're not distinguishing between the interface
(IComparer) and *one* implementation (Comparer).

Jon

Jun 27 '08 #10

P: n/a
On Jun 17, 11:17 am, "Tony" <johansson.anders...@telia.comwrote:
You say that your code would be significantly simpler if you just called
Compare directly, preferrably avoiding all those casts:
You you mean as the code prove instead CompareTo(...) I assume
Sorry, yes, I meant CompareTo.

Jon
Jun 27 '08 #11

This discussion thread is closed

Replies have been disabled for this discussion.