重载运算符==与Equals()

时间:2009-11-19 21:00:12

标签: c# operator-overloading equals

我正在开发一个C#项目,直到现在,我已经使用了不可变对象和工厂来确保始终可以比较Foo类型的对象与==的相等性。

创建后,

Foo个对象无法更改,并且工厂始终为给定的参数集返回相同的对象。这很好用,在整个代码库中我们假设==总是用于检查相等性。

现在我需要添加一些引入边缘情况的功能,但这并不总是有效。最简单的方法是为该类型重载operator ==,以便项目中的其他代码都不需要更改。但这让我觉得有点代码味道:重载operator ==而不是Equals看起来很奇怪,我已经习惯了==检查引用相等的约定,Equals检查对象是否相等(或任何术语)。

这是一个合理的问题,还是我应该继续过载operator ==

6 个答案:

答案 0 :(得分:85)

重载 ==覆盖等于

之间存在很大差异。

当你有表达式

if (x == y) {

用于比较变量x和y的方法在编译时确定。这是运算符重载。声明x和y时使用的类型用于定义用于比较它们的方法。 x和y中的实际类型(即子类或接口实现)是无关紧要的。请考虑以下事项。

object x = "hello";
object y = 'h' + "ello"; // ensure it's a different reference

if (x == y) { // evaluates to FALSE

以及

string x = "hello";
string y = 'h' + "ello"; // ensure it's a different reference

if (x == y) { // evaluates to TRUE

这表明用于声明变量x和y的类型用于确定用于评估==的方法。

通过比较,根据变量x中的实际类型,在运行时确定等于。 Equals是Object上的一个虚方法,其他类型可以并且确实覆盖它。因此,以下两个例子都评估为真。

object x = "hello";
object y = 'h' + "ello"; // ensure it's a different reference

if (x.Equals(y)) { // evaluates to TRUE

以及

string x = "hello";
string y = 'h' + "ello"; // ensure it's a different reference

if (x.Equals(y)) { // also evaluates to TRUE

答案 1 :(得分:27)

我认为标准是对于大多数类型,.Equals检查对象的相似性,而运算符==检查引用相等。

我认为最佳做法是,对于不可变类型,运算符==应该检查相似性,以及.Equals。如果您想知道它们是否真的是同一个对象,请使用.ReferenceEquals。有关此示例,请参阅C#String类。

答案 2 :(得分:7)

对于不可变类型,我认为重载==以支持值相等没有任何问题。我不认为我会覆盖==而不会覆盖Equals以获得相同的语义。如果您覆盖==并且由于某种原因需要检查引用相等性,则可以使用Object.ReferenceEquals(a,b)

请参阅此Microsoft article for some useful guidelines

答案 3 :(得分:7)

它绝对闻起来。当重载==时,您应该确保Equals()GetHashCode()都一致。请参阅MSDN guidelines

这个似乎没问题的唯一原因是你将你的类型描述为不可变的。

答案 4 :(得分:6)

示例显示如何根据MSFT guidelines(下文)实现此目的。注意,当覆盖Equals时,您还需要覆盖GetHashCode()。希望这有助于人们。

public class Person
{
    public Guid Id { get; private set; }

    public Person(Guid id)
    {
        Id = id;
    }

    public Person()
    {
        Id = System.Guid.NewGuid();
    }

    public static bool operator ==(Person p1, Person p2)
    {
        bool rc;

        if (System.Object.ReferenceEquals(p1, p2))
        {
            rc = true;
        }
        else if (((object)p1 == null) || ((object)p2 == null))
        {
            rc = false;
        }
        else
        {
            rc = (p1.Id.CompareTo(p2.Id) == 0);
        }

        return rc;
    }

    public static bool operator !=(Person p1, Person p2)
    {
        return !(p1 == p2);
    }

    public override bool Equals(object obj)
    {
        bool rc = false;
        if (obj is Person)
        {
            Person p2 = obj as Person;
            rc = (this == p2);
        }
        return rc;
    }

    public override int GetHashCode()
    {
        return Id.GetHashCode();
    }
}

答案 5 :(得分:5)

根据Microsofts自己的最佳实践,Equals方法和equals(==)重载的结果应该是相同的。

CA2224: Override equals on overloading operator equals