Syntax help: Making an IComparer for a Generic of Generics

W

wpmccormick

I'm trying to make a custom Comparer for a priority queue and I am
stumped on the syntax for the Generics. I think I almost have it
(below) except for where the ??'s are. Anybody done this before?


Thanks,

Bill

struct Item<TValue, TPriority> { }

class MyComparer<T??> : IComparer<Item<V,P>
where T : IComparable<Item<V, P>> {
public int Compare(Item<V, P> obj1, Item<V, P> obj2) {
}

public class Queue<TValue, TPriority> :
IEnumerable<Item<TValue, TPriority>>, ICloneable {

protected IComparer<Item<TValue, TPriority>>
specialComparer = new MyComparer<Item<TValue,
TPriority>>();
....
....
}
 
J

Jeroen Mostert

wpmccormick said:
I'm trying to make a custom Comparer for a priority queue and I am
stumped on the syntax for the Generics. I think I almost have it
(below) except for where the ??'s are. Anybody done this before?

struct Item<TValue, TPriority> { }
Note that this struct has a natural ordering on priority. You may want to
have it implement IComparable<TPriority>, which will simplify things
considerably. If you must include TValue as well in the comparison, this
won't work, but then you have to ask yourself why you need to include TValue
if you already have priority -- it's redundant, since the priority could be
based on the value.

That said, let's assume this struct can't be supplied with a natural
ordering and we need to supply one separately.
class MyComparer<T??> : IComparer<Item<V,P>
where T : IComparable<Item<V, P>> {
public int Compare(Item<V, P> obj1, Item<V, P> obj2) {
}
This is usually not how you do it. You either have a type that implements
IComparable or one that implements IComparer, but not some kind of mix.
They're used in different situations: IComparable supplies a natural
ordering to a type, IComparer allows for external order.

Going back to the remarks above, you could have a comparer like this if you
want to implement custom ordering on the value but not the priority (for
example) Having it to implement custom ordering on *both* the value and the
priority is meaningless, because in that case you can just use a generic
IComparer said:
public class Queue<TValue, TPriority> :
IEnumerable<Item<TValue, TPriority>>, ICloneable {

protected IComparer<Item<TValue, TPriority>>
specialComparer = new MyComparer<Item<TValue,
TPriority>>();

As far as I can tell, you definitely want Item to implement IComparable.
Then the custom comparer is entirely optional, and a default comparer (that
will use the IComparable implementation) is supplied by the static .Default
property:

public Queue() {
comparer = Comparer<Item<TValue, TPriority>>.Default;
}

public Queue(IComparer<Item<TValue, TPriority>> comparer) {
this.comparer = comparer;
}

You could also offer a way to combine two different comparers, with the
priority comparer taking precedence:

class ItemComparer<TValue, TPriority>: IComparer<Item<TValue, TPriority>> {
private readonly IComparer<TPriority> priorityComparer;
private readonly IComparer<TValue> valueComparer;

...constructor...

public int Compare(Item<TValue, TPriority> x, Item<TValue, TPriority> y) {
return Math.Sign(priorityComparer.Compare(x.Priority, y.Priority)) *
2 + valueComparer.Compare(x.Value, y.Value);
}
}

Lots of ways to go here.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top