微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

C# 9.0 中列表的记录相等

如何解决C# 9.0 中列表的记录相等

我今天正在试验 C# 9.0 功能,并注意到当 record 具有 List<Point2d> 时,列表中具有相同项目的两条记录不再相等。 Point2d 也是此处的 record

public sealed record Point2d
{
    public Point2d(double x,double y)
    {
        X = x;
        Y = y;
    }

    public double X { get; }
    public double Y { get; }
}

public sealed record polyline2d
{
    private readonly List<Point2d> _corners;

    public polyline2d(IEnumerable<Point2d> corners)
    {
        _corners = new List<Point2d>(corners);
    }
}

        polyline2d a = new (new Point2d[] { new(0,0),new(1,1),new(2,2)});
        polyline2d b = new (new Point2d[] { new(0,2) });

        a == b => false

如果我手动为 record 添加相等方法并重新定义 Equals() 方法,那么一切都会再次正常:

    public bool Equals(polyline2d other)
    {
        return other != null && _corners.SequenceEqual(other._corners);
    }

    public override int GetHashCode()
    {
        return 42;
    }


    a == b => true

这是解决此问题的正确方法,还是我需要考虑记录数据类型的其他注意事项?

解决方法

记录的自动生成的相等比较对所有字段使用默认的相等比较器(顺便说一句,自始至终,值类型也是如此)。 List<T> 的默认相等比较器只是引用相等。所以它或多或少相当于:

public bool Equals(Polyline2d other)
{
    return other != null && _corners.Equals(other._corners);
}

没有意外,您的解决方案是正确的 - 如果您想使用 SequenceEqual,您需要自己定义 Equals另请注意,您无需重新定义 GetHashCode,即使您指定自己的 Equals,编译器仍会生成自己的版本(但自动生成的 GetHashCode 仍将使用List<T> 的默认比较器的 GetHashCode 这是一些不好的建议,感谢 Jeremy Lakeman 指出这一点。如果 GetHashCode 返回不同的值对于两个实例,Equals 必须为它们返回 false,因此您实际上需要覆盖 GetHashCode,以便序列相等的列表不会返回不同的哈希码,默认实现就是这种情况。


免责声明:合成的 Equals 中的逻辑比这复杂得多,因为它实际上使用了 EqualityComparer<List<Point2d>>.Default 并考虑了记录继承,但在这种情况下无关紧要。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。