Overloading operator== versus Equals()

陌路散爱 提交于 2019-11-26 21:53:57
McKay

I believe the standard is that for most types, .Equals checks object similarity, and operator == checks reference equality.

I believe best practice is that for immutable types, operator == should be checking for similarity, as well as .Equals. And if you want to know if they really are the same object, use .ReferenceEquals. See the C# String class for an example of this.

Samuel Neff

There's a big difference between overloading == and overriding Equals.

When you have the expression

if (x == y) {

The method that will be used to compare variables x and y is decided at compile time. This is operator overloading. The type used when declaring x and y is used to define which method is used to compare them. The actual type within x and y (i.e., a subclass or interface implementation) is irrelevant. Consider the following.

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

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

and the following

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

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

This demonstrates that the type used to declare the variables x and y is used to determine which method is used to evaluate ==.

By comparison, Equals is determined at runtime based on the actual type within the variable x. Equals is a virtual method on Object that other types can, and do, override. Therefore the following two examples both evaluate to true.

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

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

and the following

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

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

It definitely smells. When overloading == you should make sure that both Equals() and GetHashCode() are also consistent. See the MSDN guidelines.

And the only reason that this seems OK at all is that you describe your type as immutable.

Mike Sackton

For immutable types I don't think there is anything wrong with having == overloaded to support value equality. I don't think I'd override == without overriding Equals to have the same semantics however. If you do override == and need to check reference equality for some reason, you can use Object.ReferenceEquals(a,b).

See this Microsoft article for some useful guidelines

John

Sample showing how to implement this according to MSFT guidelines (below). Notice, when overriding Equals you also need to override GetHashCode(). Hope this helps folks.

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();
    }
}
Ykok

According to Microsofts own best practises the outcome of the Equals method and the equals (==) overload should be the same.

CA2224: Override equals on overloading operator equals

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!