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)
交叉点是空列表,但应该包含两个元素.
IEqualityComparer是一个可以给Intersect方法比较项目的接口.默认情况下,它不用于比较任何内容.所以,你的代码只使用内置Equals在Object其中,除非对象是同一个对象将返回false.
您必须覆盖类中的默认值Equal和GetHashCode方法,或者告诉交集使用比较器的实现.但是您不应该在数据存储类中实现比较器.
你应该覆盖Equals和GetHashCode从对象:
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的评论中所提到的,您还应该重新考虑您的哈希代码实现.