2

Can someone help me understand why this doesn't work and how can make it work?

PriorityQueue<Candidate, int> pq = 
   new PriorityQueue<Candidate, int>(new EstimateCompare());
    
public class EstimateCompare: IComparer<Candidate>
{
    public int Compare(Candidate a, Candidate b)
    {
        int diff = a.estimateDistance -b.estimateDistance;
        return diff == 0 ? 0 : diff < 0 ? 1 : -1;
    }
}

Here is the error I get:

CS0535: 'EstimateCompare' does not implement interface member 'IComparer.Compare(int, int)' (in Solution.cs)

Tried using it like this and I get this error:

PriorityQueue<Candidate, int> pq = 
                    new PriorityQueue<Candidate, int>(new EstimateCompare());

public class EstimateCompare: IComparer<Candidate> {
      public int Compare(Candidate a, Candidate b) {
         return a.estimateDistance.CompareTo(b.estimateDistance);
     }

error CS1503: Argument 1: cannot convert from 'EstimateCompare' to 'System.Collections.Generic.IComparer?'

public class Candidate {
    int row;
    int col;
    int distanceSoFar;
    public int estimateDistance;
    
    public Candidate(int row, int col, int distanceSoFar, int estimateDistance) {
        this.row = row;
        this.col = col;
        this.distanceSoFar = distanceSoFar;
        this.estimateDistance = estimateDistance;
    }
}

Many Thanks!!

AlreadyLost
  • 767
  • 2
  • 13
  • 28
  • 1
    From the docs: "We recommend that you derive from the Comparer class instead of implementing the IComparer interface, because the Comparer class provides an explicit interface implementation of the IComparer.Compare method and the Default property that gets the default comparer for the object." – ddastrodd Jun 19 '22 at 22:34
  • Can you show it by an example? – AlreadyLost Jun 19 '22 at 22:39
  • Take a look here: https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.comparer-1?view=net-6.0. It has sample code where it repeats the warning to derive from Comparer, not IComparer. I don't know if that will solve your problem, but it's worth trying first. – ddastrodd Jun 19 '22 at 23:20
  • This also seems relevant to your situation: https://stackoverflow.com/questions/1487193/cannot-convert-to-icomparer – ddastrodd Jun 19 '22 at 23:26
  • Thanks for sharing these two links. I have seen both of them before. I have a similar example that works for Sort but now it is not working for PriorityQueue. I am missing something here, have reviewed these two links and tried different combinations – AlreadyLost Jun 19 '22 at 23:28
  • I was following this https://code-maze.com/csharp-priority-queue/ and not sure why it does not work for me – AlreadyLost Jun 19 '22 at 23:29
  • 1
    Can you share your code for the Candidate class? – ddastrodd Jun 20 '22 at 14:47

1 Answers1

2

The constructor you're using is PriorityQueue<TElement, TPriority>(IComparer<TPriority>), that is, TElement is Candidate, and TPriority is int, so the argument should be an instance of IComparer<int>, but EstimateCompare is an IComparer<Candidate>.

So for example, the example compiles if you instead used

PriorityQueue<Candidate, Candidate> pq = 
    new PriorityQueue<Candidate, Candidate>(new EstimateCompare());

But given what your implementation of Compare looks like, you probably don't want an IComparer at all, and you could instead do with your PriorityQueue<Candidate, int> and just use, say

pq.Enqueue(candidate, candidate.estimateDistance)

when adding elements to the queue.

fuglede
  • 17,388
  • 2
  • 54
  • 99