Using IComparer <T> .Compare (T, T) in C #

I'm trying to create a generic priority queue but int EnQueue, but I still can't seem to deal with the errors that I get using IComparer.

Error: Error 1 An object reference is required for a 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);
    }

      

+3


source to share


1 answer


What happened

you need an instance IComparer<T>

to be able to call a method Compare

on it ... remember that this is an interface, it has no static methods.

This is why it doesn't work:

IComparer<T>.Compare(start.data, dat) > 0

      

On the other hand, Comparer<T>

is a class and offers you a static property Default

that gives you an instance IComparer<T>

...

This is why it works:

Comparer<T>.Default.Compare(q.next.data, dat) < 0

      


Getting an instance IComparer<T>

You might consider storing the field with your instance IComparer<T>

and using that. This will minimize confusion and also allow you to get IComparer<T>

in the constructor to be stored in that field - which is useful if the client wants to create custom behavior.


Default instance

If you want to use the default matcher, you can get it from it:

var comparer = Comparer<T>.Default;

      

This comparator will give the default behavior for whatever is used T

. This behavior is equivalent to being called CompareTo

on instances T

with additional handling for zeros. Since you cannot use the method CompareTo

when your int is is null, you can check for null before calling CompareTo

... using a matcher fixes the problem.


Implementation IComparer<T>

Since it IComparer<T>

is an interface, you can write a class to implement it, this class must have a method Compare

with whatever logic you want. Then you instantiate this class and use it wherever the system wants IComparer<T>

.

See implementation example 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 comparator will be an instance of the class:

var comparer = new BoxComp();

      

Note : the documentation actually suggests inheriting from Comparer<T>

instead of direct IComparer<T>

, the pragmatic reason is that it Comparer<T>

also implements IComparer

in addition to IComparer<T>

.


Create IComparer<T>

with a delegate

If you are not familiar with what a delegate is, let's say it is a method reference, so you can have a variable that references a method and passes it.

You can create IComparer<T>

if you have a method delegate that does the comparison ... this is done by calling the method the Comparer<T>.Create

witch will take the delegate to the desired method. For example, you can use lambda expresion like this:

var comparer = Comparer<string>.Create
(
    (str1, str2) => str1.Length.CompareTo(str2.Length)
);

      

The above code is shorthand for this:

Comparison<string> comparison = (str1, str2) => str1.Length.CompareTo(str2.Length);
var comparer = Comparer<string>.Create(comparison);

      

This, in turn, is shorthand for this:

Comparison<string> comparison = delegate(string str1, string str2)
{
   return str1.Length.CompareTo(str2.Length);
};
var comparer = Comparer<string>.Create(comparison);

      

What 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);
}

      


Additional indications :

+7


source







All Articles