I've been trying to make a generic Reverse Priority Queue, but int the EnQueue, but I still can't manage the errors that come with using IComparer.
The Error: Error 1 An object reference is required for the non-static field, method, or property 'System.Collections.Generic.IComparer.Compare(T, T)'
public void inQ(T dat)//adding element in place, increasing order
{
if (start == null)//that means that the RPQ is empty
{
start = new node(dat);
return;
}
if (IComparer<T>.Compare(start.data, dat) > 0)//Doesn't work
{
start = new node(dat, start);
return;
}
//Default Case
//no need for an else, actually
node q = start;
while (q.next != null && Comparer<T>.Default.Compare(q.next.data, dat) < 0)//Works Perfectly
q++;
q.next = new node(dat, q.next);
}
you need an instance of IComparer<T>
to be able to call the method Compare
on it... remember this is an interface, it doesn't have static methods.
That's why this doesn't work:
IComparer<T>.Compare(start.data, dat) > 0
On the other hand Comparer<T>
is a class and it offers you an static property Default
that gives you an instance of IComparer<T>
...
That's why this works:
Comparer<T>.Default.Compare(q.next.data, dat) < 0
IComparer<T>
You can consider storing a field with your instance of IComparer<T>
and using that instead. That will minimize confusion, and also allow you to get an IComparer<T>
in the constructor to be stored on that field - which is useful in case the client wants a custom behaviour.
If you want to use the default comparer you can get it from it:
var comparer = Comparer<T>.Default;
This comparer will give the default behaviour for whatever T
you use. This behaviour is equivalent to calling CompareTo
on the instances of T
, with extra handling for nulls. Since you cannot use the method CompareTo
when your intance is null you may want to check for null before calling CompareTo
... using a comparer removes the problem.
IComparer<T>
Since IComparer<T>
is an interface, you can write a class to implement it, that class must have a Compare
method with whatever logic you want. Then you create an instance of that class and use it where the system wants an IComparer<T>
.
See the an example of implementing IComparer<T>
on MSDN
// This class is not demonstrated in the Main method
// and is provided only to show how to implement
// the interface. It is recommended to derive
// from Comparer<T> instead of implementing IComparer<T>.
public class BoxComp : IComparer<Box>
{
// Compares by Height, Length, and Width.
public int Compare(Box x, Box y)
{
if (x.Height.CompareTo(y.Height) != 0)
{
return x.Height.CompareTo(y.Height);
}
else if (x.Length.CompareTo(y.Length) != 0)
{
return x.Length.CompareTo(y.Length);
}
else if (x.Width.CompareTo(y.Width) != 0)
{
return x.Width.CompareTo(y.Width);
}
else
{
return 0;
}
}
}
Your comparer would be an instance of the class:
var comparer = new BoxComp();
Note: the documentation actually suggest to inherit from Comparer<T>
instead of implementing IComparer<T>
directly, the pragmatic reason is that Comparer<T>
also implements IComparer
in addition of IComparer<T>
.
IComparer<T>
with a delegateIn case you are not familiar with what a delegate is, let's say it is a reference to a method, so you can have a variable that has a reference to method and pass it around.
You can create an IComparer<T>
if you have a delegate to a method that does the comparison... this is done by calling the method Comparer<T>.Create
witch will take a delegate to the method you want. For example you can use a lambda expresion as follows:
var comparer = Comparer<string>.Create
(
(str1, str2) => str1.Length.CompareTo(str2.Length)
);
The code above is a shorthand for this:
Comparison<string> comparison = (str1, str2) => str1.Length.CompareTo(str2.Length);
var comparer = Comparer<string>.Create(comparison);
Which in turn is a shorthand for this:
Comparison<string> comparison = delegate(string str1, string str2)
{
return str1.Length.CompareTo(str2.Length);
};
var comparer = Comparer<string>.Create(comparison);
Which is sugar for something like this (except that in the above code the method is anonymous):
Comparison<string> comparison = StringComparison;
var comparer = Comparer<string>.Create(comparison);
// ...
private static int StringComparison(string str1, string str2)
{
return str1.Length.CompareTo(str2.Length);
}
Extra readings:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With