== or .Equals()

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

  • http://blogs.msdn.com/csharpfaq/archive/2004/03/29/102224.aspx

@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();


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


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


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
    }
}