【问题标题】:Equality of records with lists in C# 9.0 [duplicate]C# 9.0 中的记录与列表的相等性 [重复]
【发布时间】:2021-05-09 21:29:42
【问题描述】:

我今天正在试验 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, 0), new(1, 1), new(2, 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

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

【问题讨论】:

  • 感谢 Jeremey 编辑问题。

标签: c# record equality c#-9.0 c#-record-type


【解决方案1】:

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

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

没有什么意外,您的解决方案是正确的 - 如果您想使用 SequenceEqual,您需要自己定义 Equals还要注意你不需要重新定义GetHashCode,即使你指定了自己的Equals,编译器仍然会生成自己的版本(但是自动生成的GetHashCode仍然会使用List&lt;T&gt;的默认值比较器的GetHashCode)。 这是一些不好的建议,感谢 Jeremy Lakeman 指出这一点。如果 GetHashCode 为两个实例返回不同的值,那么 Equals 必须为它们返回 false , 所以实际上你确实需要覆盖 GetHashCode 以便序列相等的列表不会返回不同的哈希码,这是默认实现的情况。


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

【讨论】:

  • 如果.Equals() 表示它们相等,.GetHashCode() 应该返回相同的值。一般来说,如果你覆盖一个,你应该覆盖另一个。或者你会在 HashSet / Dictionary Key 中得到令人惊讶的结果。
  • @JeremyLakeman 你是对的,我在脑海中混淆了哈希码的语义,并认为在这种情况下它会很好,但事实并非如此。有趣的是,当我在我的 IDE 中输入不同的 Equals 时,它甚至会给你一个警告 CS8851:'Polyline2d' 定义了 'Equals' 但没有定义 'GetHashCode',所以幸运的是编译器比我更聪明,并且会发出警告。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-02-25
  • 1970-01-01
  • 1970-01-01
  • 2012-03-25
  • 2014-05-26
  • 2012-03-03
  • 2013-09-02
相关资源
最近更新 更多