两个点的C#集合不会返回任何结果

Fre*_*kyB 1 c# linq iequalitycomparer

类:

public class Point : IEqualityComparer<Point>
{               
    public char HorizontalPosition { get; set; }
    public int VerticalPosition { get; set; }

    public Point(char horizontalPosition, int verticalPosition)
    {
        HorizontalPosition = char.ToUpper(horizontalPosition);
        VerticalPosition = verticalPosition;           
    }   

    public bool Equals(Point x, Point y)
    {
        return (x.VerticalPosition == y.VerticalPosition && x.HorizontalPosition == y.HorizontalPosition);
    }

    public int GetHashCode(Point obj)
    {
        return (obj.HorizontalPosition.GetHashCode() + obj.VerticalPosition.GetHashCode());
    }
}
Run Code Online (Sandbox Code Playgroud)

我试图在两个集合中找到共同点(交集),但结果是空集合 - 其中应包含两个元素.为什么?我已经实现了IEqualityComparer.我做错了什么吗?

示例集合:

  List<Point> first = new List<Point> { new Point('a', 1), new Point('b', 2) };
  List<Point> second = new List<Point> { new Point('a', 1), new Point('b', 2) };
  List<Point> intersection = first.Intersect(second).ToList();
Run Code Online (Sandbox Code Playgroud)

交叉点是空列表,但应该包含两个元素.

Sam*_*nen 5

IEqualityComparer是一个可以给Intersect方法比较项目的接口.默认情况下,它不用于比较任何内容.所以,你的代码只使用内置EqualsObject其中,除非对象是同一个对象将返回false.

您必须覆盖类中的默认值EqualGetHashCode方法,或者告诉交集使用比较器的实现.但是您不应该在数据存储类中实现比较器.


Nic*_*ico 5

你应该覆盖EqualsGetHashCode从对象:

public class Point
{
    public char HorizontalPosition { get; set; }
    public int VerticalPosition { get; set; }

    public Point(char horizontalPosition, int verticalPosition)
    {
        HorizontalPosition = char.ToUpper(horizontalPosition);
        VerticalPosition = verticalPosition;
    }

    public override int GetHashCode()
    {
        unchecked
        { 
            return (HorizontalPosition * 397) ^ VerticalPosition;
        }
    }

    protected bool Equals(Point other)
    {
        return Equals(HorizontalPosition, other.HorizontalPosition) && Equals(VerticalPosition, other.VerticalPosition);
    }

    public override bool Equals(object obj)
    {
        if (ReferenceEquals(null, obj)) return false;
        if (ReferenceEquals(this, obj)) return true;
        if (obj.GetType() != this.GetType()) return false;
        return Equals((Point)obj);
    }
}
Run Code Online (Sandbox Code Playgroud)

您还可以实现自定义IEqualityComparer并将其传递给intersect:

public class PointComparer : IEqualityComparer<Point>
{
    public bool Equals(Point a, Point b)
    {
        return a.HorizontalPosition == b.HorizontalPosition && a.VerticalPosition == b.VerticalPosition;
    }

    public int GetHashCode(Point p)
    {
        unchecked
        { 
            return (p.HorizontalPosition * 397) ^ p.VerticalPosition;
        }
    }
}

// ...

List<Point> intersection = first.Intersect(second, new PointComparer()).ToList();
Run Code Online (Sandbox Code Playgroud)

正如@decPL的评论中所提到的,您还应该重新考虑您的哈希代码实现.