c# - 什么是用于比较引用类型的两个实例的 "Best Practice"?

标签 c# .net comparison operator-overloading equality

我最近遇到了这个问题,到目前为止,我一直很高兴地重写相等运算符 (==) 和/或 Equals 方法以查看两个引用是否类型实际上包含相同的数据(即两个看起来相同的不同实例)。

自从我越来越多地参与自动化测试(将引用/预期数据与返回的数据进行比较)以来,我一直在更多地使用它。

在查看一些 coding standards guidelines in MSDN 时我遇到了 article建议反对它。现在我明白了为什么这篇文章是这样说的(因为它们不是同一个实例)但它没有回答问题:

  1. 比较两种引用类型的最佳方法是什么?
  2. 我们应该实现 IComparable ? (我还看到提到这应该只为值类型保留)。
  3. 是否有一些我不知道的接口(interface)?
  4. 我们应该自己动手吗?!

非常感谢^_^

更新

看起来我误读了一些文档(这是漫长的一天)并覆盖了 Equals可能是要走的路..

If you are implementing reference types, you should consider overriding the Equals method on a reference type if your type looks like a base type such as a Point, String, BigNumber, and so on. Most reference types should not overload the equality operator, even if they override Equals. However, if you are implementing a reference type that is intended to have value semantics, such as a complex number type, you should override the equality operator.

最佳答案

在 .NET 中正确、高效地实现相等性并且没有代码重复是很困难的。具体来说,对于具有值语义的引用类型(即 immutable types that treat equvialence as equality ),您应该实现 the System.IEquatable<T> interface ,并且您应该实现所有不同的操作( EqualsGetHashCode==!= )。

例如,这是一个实现值相等的类:

class Point : IEquatable<Point> {
    public int X { get; }
    public int Y { get; }

    public Point(int x = 0, int y = 0) { X = x; Y = y; }

    public bool Equals(Point other) {
        if (other is null) return false;
        <b>return X.Equals(other.X) && Y.Equals(other.Y);</b>
    }

    public override bool Equals(object obj) => Equals(obj as Point);

    public static bool operator ==(Point lhs, Point rhs) => object.Equals(lhs, rhs);

    public static bool operator !=(Point lhs, Point rhs) => ! (lhs == rhs);

    public override int GetHashCode() => <b>X.GetHashCode() ^ Y.GetHashCode();</b>
}

以上代码中唯一可移动的部分是粗体部分:Equals(Point other) 中的第二行和 GetHashCode()方法。其他代码保持不变。

对于不表示不可变值的引用类,不要实现运算符 ==!= .相反,使用它们的默认含义,即比较对象标识。

代码有意甚至将派生类类型的对象等同起来。通常,这可能是不可取的,因为基类和派生类之间的相等性没有明确定义。不幸的是,.NET 和编码准则在这里不是很清楚。 Resharper 创建的代码,已发布 in another answer , 在这种情况下容易出现不良行为,因为 Equals(object x)Equals(SecurableResourcePermission x) 以不同的方式处理这种情况。

为了改变这种行为,必须在强类型 Equals 中插入额外的类型检查。方法如上:

public bool Equals(Point other) {
    if (other is null) return false;
    if (other.GetType() != GetType()) return false;
    <b>return X.Equals(other.X) && Y.Equals(other.Y);</b>
}

关于c# - 什么是用于比较引用类型的两个实例的 "Best Practice"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/104158/

相关文章:

.net - F5浏览器刷新和回发有区别吗?(asp.NET)

c# - 如何在 C# 中定义 "include"?

javascript - javascript 运算符 === 和 lodash 方法 _.eq() 之间的区别?

javascript - 日期和数字之间的相等比较不起作用

c# - 要命令的 XAML Setter 属性

c# - IIS 中的 WCF,http 基本身份验证 - Windows 用户 "security"含义

javascript - 如何停止 Razors 自动编码\n?

c# - 给定一个受约束的泛型方法,我可以调用一个传递泛型参数实际类型的非泛型方法吗

c# - FluentAssertions : ShouldBeEquivalentTo vs Should(). Be() vs Should().BeEquivalentTo()?

c# - 如何使用 StackExchange.Redis 进行基本 WATCH