78

Why use one over the other?

Dimitri C.
  • 21,861
  • 21
  • 85
  • 101
Dan
  • 29,100
  • 43
  • 148
  • 207
  • 7
    Note for anyone who searches and finds this answer, both `Equals` and `==` can be overloaded, so the exact results of calling one or the other will vary. For instance `string` performs an equality test for `==`. Also note that the semantics of both can be [complex](http://blogs.msdn.com/b/ericlippert/archive/2009/04/09/double-your-dispatch-double-your-fun.aspx). – Guvante Oct 01 '12 at 19:58
  • possible duplicate of [C# difference between \`==\` and .Equals()](http://stackoverflow.com/questions/814878/c-sharp-difference-between-and-equals) – Michael Freidgeim Aug 26 '13 at 22:26
  • 1
    According to Microsoft Framework Design Guidelines: "DO ensure that Object.Equals and the equality operators have exactly the same semantics and similar performance characteristics." https://learn.microsoft.com/en-us/dotnet/standard/design-guidelines/equality-operators – Dave Mackersie Dec 18 '17 at 15:39

12 Answers12

65

== is the identity test. It will return true if the two objects being tested are in fact the same object. Equals() performs an equality test, and will return true if the two objects consider themselves equal.

Identity testing is faster, so you can use it when there's no need for more expensive equality tests. For example, comparing against null or the empty string.

It's possible to overload either of these to provide different behavior -- like identity testing for Equals() --, but for the sake of anybody reading your code, please don't.


Pointed out below: some types like String or DateTime provide overloads for the == operator that give it equality semantics. So the exact behavior will depend on the types of the objects you are comparing.


See also:

dtb
  • 213,145
  • 36
  • 401
  • 431
John Millikin
  • 197,344
  • 39
  • 212
  • 226
  • How would you go about overloading ==? Out of curiosity. – Brettski Sep 27 '08 at 21:42
  • 1
    @Brett: no idea, but the MSDN blog says it's possible. – John Millikin Sep 27 '08 at 21:43
  • 2
    Actually, FxCop forces you to override Equals if you are also overriding operator ==, since they should be basically the same, in contrast to ReferenceEquals. – OregonGhost Sep 27 '08 at 21:43
  • 2
    How can you say that you should never override Equals? If your objects are Equal but created in different parts of the application (say the same row fetched twice from the db) you might well say they are the same. The main thing is that Equals should correspond to the identity of the object – Oskar Sep 27 '08 at 22:50
  • 2
    == is overloaded the same way as any other operator. As for overloading .Equals(), you should if you need some measure of value equality based on value, not reference. And you should overload == if shouldn't be comparing by references (ie. value types) – Matthew Scharley Sep 28 '08 at 00:14
  • @Oskar: I mean, do not override to provide unusual behavior. Like don't make Equals() for a value type into a reference comparison. – John Millikin Sep 28 '08 at 05:54
  • string s = "a"; string r = "a"; int j =0; int i= 0; if (s == r ) j = 1; if ( s.Equals(r)) i=1; after I execute this code both i and j are set to 1. You said " It will return true if the two objects being tested are in fact the same object" the s and r objects are not same so why is that so ? – Ozgur Dogus Jun 28 '12 at 13:05
  • 2
    Because String override the == operator and call String.Equals(a, b) when you use ==. So s == r and s.Equals(r) does the exact same thing for String. [Check the source code](http://referencesource.microsoft.com/#mscorlib/system/string.cs,673) – Julien N Nov 20 '14 at 11:34
  • Equals should be overridden on types with value semantics, and overloading == should be considered to make the type feel more like a primitive type. Framework Design Guidelines: https://learn.microsoft.com/en-us/dotnet/standard/design-guidelines/equality-operators https://learn.microsoft.com/en-us/dotnet/standard/design-guidelines/operator-overloads – Dave Mackersie Dec 18 '17 at 17:47
21

@John Millikin:

Pointed out below: some value types like DateTime provide overloads for the == operator >that give it equality semantics. So the exact behavior will depend on the types of the >objects you are comparing.

To elaborate:

DateTime is implemented as a struct. All structs are children of System.ValueType.

Since System.ValueType's children live on the stack, there is no reference pointer to the heap, and thus no way to do a reference check, you must compare objects by value only.

System.ValueType overrides .Equals() and == to use a reflection based equality check, it uses reflection to compare each fields value.

Because reflection is somewhat slow, if you implement your own struct, it is important to override .Equals() and add your own value checking code, as this will be much faster. Don't just call base.Equals();

FlySwat
  • 172,459
  • 74
  • 246
  • 311
  • A DateTime might live on the heap or the stack. If it's inside a class, for instance, it'll live in the heap; Basically two values types could never be the same if they are passed by value and not by reference, right? – Luis Filipe Aug 17 '13 at 00:32
16

Everyone else pretty much has you covered, but I have one more word of advice. Every now and again, you will get someone who swears on his life (and those of his loved ones) that .Equals is more efficient/better/best-practice or some other dogmatic line. I can't speak to efficiency (well, OK, in certain circumstances I can), but I can speak to a big issue which will crop up: .Equals requires an object to exist. (Sounds stupid, but it throws people off.)

You can't do the following:

StringBuilder sb = null;
if (sb.Equals(null))
{
    // whatever
}

It seems obvious to me, and perhaps most people, that you will get a NullReferenceException. However, proponents of .Equals forget about that little factoid. Some are even "thrown" off (sorry, couldn't resist) when they see the NullRefs start to pop up.

(And years before the DailyWTF posting, I did actually work with someone who mandated that all equality checks be .Equals instead of ==. Even proving his inaccuracy didn't help. We just made damn sure to break all his other rules so that no reference returned from a method nor property was ever null, and it worked out in the end.)

Joe Clay
  • 33,401
  • 4
  • 85
  • 85
John Rudy
  • 37,282
  • 14
  • 64
  • 100
  • In this particular case, you can use `if (sb?.Equals(null) ?? true)`, but that's definitely a lot more cumbersome and less readable than `if (sb == null)`. – saluce Feb 15 '17 at 19:49
  • The official advice for overloading `Object.Equals(Object obj)` mentions explicitly returning `false` for `null` values of `obj`. It also states the implementation *should not* throw exceptions. Regardless, you can't guarantee everyone follows that sensible advice! https://learn.microsoft.com/en-us/dotnet/api/system.object.equals – jmlane Nov 14 '18 at 20:56
  • There's also the static Equals function `object.Equals(object,object)` which can take null objects. E.g.: `if (object.Equals(sb, null) {..}`, or in short `if (Equals(sb, null)) {..}` – user11909 Mar 02 '22 at 07:27
6

== is generally the "identity" equals meaning "object a is in fact the exact same object in memory as object b".

equals() means that the objects logically equal (say, from a business point of view). So if you are comparing instances of a user-defined class, you would generally need to use and define equals() if you want things like a Hashtable to work properly.

If you had the proverbial Person class with properties "Name" and "Address" and you wanted to use this Person as a key into a Hashtable containing more information about them, you would need to implement equals() (and hash) so that you could create an instance of a Person and use it as a key into the Hashtable to get the information.

Using == alone, your new instance would not be the same.

Joshua DeWald
  • 3,079
  • 20
  • 16
5

According to MSDN:

In C#, there are two different kinds of equality: reference equality (also known as identity) and value equality. Value equality is the generally understood meaning of equality: it means that two objects contain the same values. For example, two integers with the value of 2 have value equality. Reference equality means that there are not two objects to compare. Instead, there are two object references and both of them refer to the same object.

...

By default, the operator == tests for reference equality by determining whether two references indicate the same object.

Kols
  • 3,641
  • 2
  • 34
  • 42
Jason Olson
  • 3,616
  • 2
  • 21
  • 24
  • This explanation is pretty much brilliant. Also a good reference to documentation is always something solid to do. Please, extend it with some actual examples too. – carloswm85 May 02 '22 at 11:54
3

Both Equals and == can be overloaded, so the exact results of calling one or the other will vary. Note that == is determined at compile time, so while the actual implementation could change, which == is used is fixed at compile time, unlike Equals which could use a different implementation based on the run time type of the left side.

For instance string performs an equality test for ==.

Also note that the semantics of both can be complex.

Best practice is to implement equality like this example. Note that you can simplify or exclude all of this depending on how you plan on using you class, and that structs get most of this already.

class ClassName
{
    public bool Equals(ClassName other)
    {
        if (other == null)
        {
            return false;
        }
        else
        {
            //Do your equality test here.
        }
    }

    public override bool Equals(object obj)
    {
        ClassName other = obj as null; //Null and non-ClassName objects will both become null
        if (obj == null)
        {
            return false;
        }
        else
        {
            return Equals(other);
        }
    }

    public bool operator ==(ClassName left, ClassName right)
    {
        if (left == null)
        {
            return right == null;
        }
        else
        {
            return left.Equals(right);
        }
    }

    public bool operator !=(ClassName left, ClassName right)
    {
        if (left == null)
        {
            return right != null;
        }
        else
        {
            return !left.Equals(right);
        }
    }

    public override int GetHashCode()
    {
        //Return something useful here, typically all members shifted or XORed together works
    }
}
Guvante
  • 18,775
  • 1
  • 33
  • 64
  • This is not entirely true. == is overloaded while Equals is overridden, which is an important difference. So the code that is executed for a == operator is linked at compile time, while Equals is virtual and found at execution time. – Stefan Steinegger Aug 15 '13 at 06:58
  • @StefanSteinegger: Unless you are authoring libraries you will rarely run into that distinction, I went ahead and added a note. – Guvante Aug 17 '13 at 00:11
  • _"== is overloaded while Equals is overridden"_ -- Equals() can be both overloaded _and_ overridden. I mean, obviously `System.Object.Equals(object)` can only be overridden. But there's nothing stopping a class from creating additional overloads of the `Equals()` method, and indeed this is what happens any time a class implements `IEquatable`. – Peter Duniho May 07 '15 at 00:10
2

The example is because the class DateTime implements the IEquatable interface, which implements a "type-specific method for determining equality of instances." according to MSDN.

Kols
  • 3,641
  • 2
  • 34
  • 42
Peter K.
  • 8,028
  • 4
  • 48
  • 73
2

Another thing to take into consideration: the == operator may not be callable or may have different meaning if you access the object from another language. Usually, it's better to have an alternative that can be called by name.

Jason Baker
  • 192,085
  • 135
  • 376
  • 510
2

In most cases, they are the same, so you should use == for clarity. According to the Microsoft Framework Design Guidelines:

"DO ensure that Object.Equals and the equality operators have exactly the same semantics and similar performance characteristics." https://learn.microsoft.com/en-us/dotnet/standard/design-guidelines/equality-operators

But sometimes, someone will override Object.Equals without providing equality operators. In that case, you should use Equals to test for value equality, and Object.ReferenceEquals to test for reference equality.

Dave Mackersie
  • 1,033
  • 10
  • 14
1

use equals if you want to express the contents of the objects compared should be equal. use == for primitive values or if you want to check that the objects being compared is one and the same object. For objects == checks whether the address pointer of the objects is the same.

Jasper
  • 846
  • 7
  • 14
1

I have seen Object.ReferenceEquals() used in cases where one wants to know if two references refer to the same object

GregUzelac
  • 462
  • 2
  • 6
0

If you do disassemble (by dotPeek for example) of Object, so

public virtual bool Equals(Object obj)

described as:

// Returns a boolean indicating if the passed in object obj is
// Equal to this.  Equality is defined as object equality for reference
// types and bitwise equality for value types using a loader trick to
// replace Equals with EqualsValue for value types). 
//

So, is depend on type. For example:

        Object o1 = "vvv";
        Object o2 = "vvv";
        bool b = o1.Equals(o2);

        o1 = 555;
        o2 = 555;
        b = o1.Equals(o2);

        o1 = new List<int> { 1, 2, 3 };
        o2 = new List<int> { 1, 2, 3 };
        b = o1.Equals(o2);

First time b is true (equal performed on value types), second time b is true (equal performed on value types), third time b is false (equal performed on reference types).

zzfima
  • 1,528
  • 1
  • 14
  • 21