在C#中实现类的"=="操作符的最佳实践是什么?

8

在实现一个==运算符时,我有一种遗漏了一些基本要点的感觉。
因此,我正在寻找一些最佳实践。
以下是我正在考虑的一些相关问题:

  • 如何清晰地处理引用比较?
  • 应该通过类似于IEquatable<T>的接口来实现吗?还是重写object.Equals
  • 那么!=运算符呢?

(这个列表可能不是详尽无遗的)。


3
请查看以下线程:https://dev59.com/uEfSa4cB1Zd3GeqPA-fT,https://dev59.com/_3M_5IYBdhLWcg3wUxjF,https://dev59.com/R3RB5IYBdhLWcg3wUVxd,https://dev59.com/uXRB5IYBdhLWcg3wn4fc。 - vgru
4个回答

10
我会遵循Microsoft的Guidelines for Overloading Equals() and Operator ==
编辑:Microsoft的指南包含这个重要的备注,似乎确认了Henk的答案:
默认情况下,运算符==通过确定两个引用是否指示相同的对象来测试引用相等性,因此引用类型不需要实现运算符==以获得这种功能。当类型是不可变的(即实例中包含的数据不能更改)时,重载运算符==以比较值相等性而不是引用相等性可能很有用,因为作为不可变对象,只要它们具有相同的值,它们就可以被视为相同。不推荐在非不可变类型中覆盖运算符==。

链接在2018年已经失效。(这就是为什么我们应该在链接的基础上引用相关文档的原因。) - rianjs
1
@rianjs 这不就是我所做的吗? - Wim Coenen
"如何实现==运算符的最佳实践是什么?"接着说:"我会遵循微软的指南<链接已失效>",引用一行曾经无疑是整个页面的内容(“避免在可变类型中执行此操作”)并不是一个特别好的答案。它不完整;对于想要了解实现==运算符的完整最佳实践集的人来说,这并不有帮助。 - rianjs
2
以下是有关编程的内容,请将其从英语翻译成中文。仅返回已翻译的文本:在软件开发中,代码重构是指对现有代码进行修改,以改善其结构、可读性、可维护性和/或性能,而不改变其外部行为。重构可以通过添加、删除或修改代码来实现,目的是使代码更易于理解和维护。重构是一种迭代过程,通常与测试紧密结合,以确保重构后的代码仍然具有正确的功能。 - Wim Coenen

6
每次实现==运算符时,一定要同时实现!=IEquatable<T>接口,并重写Object.Equals()Object.GetHashCode()方法,以保证类的用户使用一致性。
考虑一个类,以下是我的通常实现方式:
    public bool Equals(MyClass other) {
        if (ReferenceEquals(other, null))
            return false;
        if (ReferenceEquals(other, this))
            return true;
        return // your equality code here
    }

    public override bool Equals(object obj) {
        return Equals(obj as MyClass);
    }

    public override int GetHashCode() {
        return // your hash function here
    }

    public static bool operator ==(MyClass left, MyClass right) {
        return Equals(left, right);
    }

    public static bool operator !=(MyClass left, MyClass right) {
        return !(left == right);
    }

此外,如果您最初实现了一个小于(<)运算符,那么您可以仅使用该运算符来实现每个其他运算符。例如:如果已经实现了<运算符,则可以将==表示为!(left < right || right < left)。 - Jesse O'Brien

4
  • 如果你实现了 ==,那么还要重写 .Equals 和 .GetHashCode
  • 同时也要实现 !=
  • 使用 object.ReferenceEquals 检查空引用,否则操作符将递归

2
实际上,你必须实现“!=”,否则 C# 就不会让你编译。 - Maximilian Mayerl

3
最常见的做法是去处理它。默认值是引用比较,这通常对于类对象来说是正确的。
因此,首先您需要非常确定您需要值类型行为。

2
让我们明确回答问题,而不是告诉别人改变做事方式的建议。 - Akash Kava

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接