== or .Equals()
Asked Answered
S

12

79

Why use one over the other?

Stpierre answered 27/9, 2008 at 21:36 Comment(3)
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.Schlicher
possible duplicate of C# difference between `==` and .Equals()Equality
According to Microsoft Framework Design Guidelines: "DO ensure that Object.Equals and the equality operators have exactly the same semantics and similar performance characteristics." learn.microsoft.com/en-us/dotnet/standard/design-guidelines/…Oblong
V
66

== 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:

Vite answered 27/9, 2008 at 21:39 Comment(9)
How would you go about overloading ==? Out of curiosity.Riha
@Brett: no idea, but the MSDN blog says it's possible.Vite
Actually, FxCop forces you to override Equals if you are also overriding operator ==, since they should be basically the same, in contrast to ReferenceEquals.Junto
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 objectGuernsey
== 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)Loretaloretta
@Oskar: I mean, do not override to provide unusual behavior. Like don't make Equals() for a value type into a reference comparison.Vite
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 ?Emanation
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 codeLanky
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: learn.microsoft.com/en-us/dotnet/standard/design-guidelines/… learn.microsoft.com/en-us/dotnet/standard/design-guidelines/…Oblong
B
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();

Britten answered 27/9, 2008 at 22:19 Comment(1)
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?Dexamyl
S
15

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.)

Synagogue answered 27/9, 2008 at 21:56 Comment(3)
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).Quetzal
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! learn.microsoft.com/en-us/dotnet/api/system.object.equalsKinkajou
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)) {..}Flywheel
M
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.

Mcfarlane answered 27/9, 2008 at 21:41 Comment(0)
E
6

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.

Exhort answered 27/9, 2008 at 21:42 Comment(1)
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.Redletter
S
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
    }
}
Schlicher answered 1/10, 2012 at 20:3 Comment(3)
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.Bentlee
@StefanSteinegger: Unless you are authoring libraries you will rarely run into that distinction, I went ahead and added a note.Schlicher
"== 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<T>.Trombidiasis
M
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.

Mizzen answered 27/9, 2008 at 21:53 Comment(0)
I
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.

Idiotism answered 27/9, 2008 at 21:54 Comment(0)
O
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.

Oblong answered 18/12, 2017 at 16:8 Comment(0)
G
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.

Gymnastics answered 27/9, 2008 at 21:40 Comment(0)
F
1

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

Fadeout answered 16/10, 2008 at 2:47 Comment(0)
H
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).

Heptad answered 16/6, 2015 at 8:27 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.