Search code examples
c#iequalitycomparer

Breakpoint in Equals implimentation on IEqualityComparer<CustomClass> is never hit


I have a simple custom class Point:

    public class Point: IEqualityComparer<Point>
{
    public double X;
    public double Y;
    public double Z;
    private double[] startPointCoords;

    public Point()
    {
    }

    public Point(double[] pointArray)
    {
        this.startPointCoords = pointArray;
        X = pointArray[0];
        Y = pointArray[1];
        Z = pointArray[2];
    }

    public bool Equals(Point x, Point y)
    {
        if(x.X == y.X && x.Y == y.Y && x.Z == y.Z)
        {
            return true;
        }
        return false;
    }

    public int GetHashCode(Point obj)
    {
        string xString = X.ToString().Replace(".", "");
        string yString = Y.ToString().Replace(".", "");
        string zString = Z.ToString().Replace(".", "");
        int xInt = Convert.ToInt32(xString);
        int yInt = Convert.ToInt32(yString);
        int zInt = Convert.ToInt32(zString);
        return xInt - yInt + zInt;
    }
}

I am using this class in a Dictionary. I am checking for if the point instance has been added to the dictionary using:

            if (!pointsToProcess.ContainsKey(startPoint))
            {
                pointsToProcess.Add(startPoint, startPoint);
            }

I am debugging my code to make sure Equals is working correctly. My break point I have set in Point.Equals is never hit. I set a break point in Point.GetHashCode and it is never hit either. It seems like they are not being used.

I know that there are classes called Point in .Net. I am absolutely sure that all the Point that I have in my code is from my custom namespace.

Why would my Point.Equals and Point.GetHashCode not be reached when setting a break point?


Solution

  • The Equals(a, b) method is not hit by IEquatable, so you'll need to tailor it to suit the interface.

    Try this one:

    public class Point : IEquatable<Point>
    {
        public double X;
        public double Y;
        public double Z;
        private double[] startPointCoords;
    
        public Point()
        {
        }
    
        public Point(double[] pointArray)
        {
            this.startPointCoords = pointArray;
            X = pointArray[0];
            Y = pointArray[1];
            Z = pointArray[2];
        }
    
        public override bool Equals(object obj) => Equals(obj as Point);
    
        public bool Equals(Point other)
        {
            if (other is null)
                return false;
    
            if (ReferenceEquals(this, other))
                return true;
    
            return this.X == other.X &&
                   this.Y == other.Y &&
                   this.Z == other.Z;
        }
    
        public override int GetHashCode()
        {
            string xString = X.ToString().Replace(".", "");
            string yString = Y.ToString().Replace(".", "");
            string zString = Z.ToString().Replace(".", "");
            int xInt = Convert.ToInt32(xString);
            int yInt = Convert.ToInt32(yString);
            int zInt = Convert.ToInt32(zString);
            return xInt - yInt + zInt;
        }
    
    }
    

    Also there are a lot of ways to implement hashcodes in C# for custom objects. While not perfect, one simple way would be using anonymous object hashing:

    public override int GetHashCode()
    {
        return new { X, Y, Z }.GetHashCode();
    }