tags:

views:

744

answers:

8

What is the difference between a.Equals(b) and a == b for value types, reference types, and strings? It would seem as though a == b works just fine for strings, but I'm trying to be sure to use good coding practices.

A: 

"==" is an operator that can be overloaded to perform different things based on the types being compared.

The default operation performed by "==" is a.Equals(b);

Here's how you could overload this operator for string types:

public static bool operator == (string str1, string str2) 
{
    return (str1.Length == str2.Length;)
}

Note that this is different than str1.Equals(str2);

Derived classes can also override and redefine Equals().

As far as "best practices" go, it depends on your intent.

Josh G
Could you clarify what yo mean by "The default operation performed by "==" is a.Equals(b)".
Steve Haigh
If you don't overload the '==' operator, it does the same thing as the Equals() function does. For strings, it does a string comparison, for user types it compares references.
Josh G
+6  A: 

At a simple level, the difference is which method is called. The == method will attempt ot bind to operator== if defined for the types in question. If no == is found for value types it will do a value comparison and for reference types it will do a reference comparison. A .Equals call will do a virtual dispatch on the .Equals method.

As to what the particular methods do, it's all in the code. Users can define / override these methods and do anything they please. Ideally this methods should be equivalent (sorry for the pun) and have the same output but it is not always the case.

JaredPar
+1 Good to mention that Equals is a virtual method.
Andrew Hare
+10  A: 

From When should I use Equals and when should I use ==:

The Equals method is just a virtual one defined in System.Object, and overridden by whichever classes choose to do so. The == operator is an operator which can be overloaded by classes, but which usually has identity behaviour.

For reference types where == has not been overloaded, it compares whether two references refer to the same object - which is exactly what the implementation of Equals does in System.Object.

Value types do not provide an overload for == by default. However, most of the value types provided by the framework provide their own overload. The default implementation of Equals for a value type is provided by ValueType, and uses reflection to make the comparison, which makes it significantly slower than a type-specific implementation normally would be. This implementation also calls Equals on pairs of references within the two values being compared.

using System;

public class Test
{
    static void Main()
    {
        // Create two equal but distinct strings
        string a = new string(new char[] {'h', 'e', 'l', 'l', 'o'});
        string b = new string(new char[] {'h', 'e', 'l', 'l', 'o'});

        Console.WriteLine (a==b);
        Console.WriteLine (a.Equals(b));

        // Now let's see what happens with the same tests but
        // with variables of type object
        object c = a;
        object d = b;

        Console.WriteLine (c==d);
        Console.WriteLine (c.Equals(d));
    }
}

The result of this short sample program is

True
True
False
True
0xA3
+2  A: 

One significant difference between them is that == is a static binary operator that works on two instances of a type whereas Equals is an instance method. The reason this matters is that you can do this:

Foo foo = new Foo()
Foo foo2 = null;
foo2 == foo;

But you cannot do this without throwing a NullReferenceException:

Foo foo = new Foo()
Foo foo2 = null;
foo2.Equals(foo);
Andrew Hare
A: 

For strings you want to be careful of culture specific comparisons. The classic example is the german double S, that looks a bit like a b. This should match with "ss" but doesn't in a simple == comparison.

For string comparisons that are culture sensitive use: String.Compare(expected, value, StringComparison....) == 0 ? with the StringComparison overload you need.

Quibblesome
A: 

By default, both == and .Equals() are equivalent apart from the possibility of calling .Equals() on a null instance (which would give you a NullReferenceException). You can, however, override the functionality of either of them independently (though I'm not sure that would ever be a good idea unless you're trying to work around the shortcomings of another system), which would mean you could MAKE them different.

You'll find people on both sides of the aisle as to the one to use. I prefer the operator rather than the function.

If you're talking about strings, though, it's likely a better idea to use string.Compare() instead of either one of those options.

Adam Robinson
+5  A: 

Here is a great blog post about WHY the implementations are different.

Essentially == is going to be bound at compile time using the types of the variables and .Equals is going to be dynamically bound at runtime.

Chris Shaffer
+1 for the Lippert link, I was looking for this earlier!
Steve Haigh
+2  A: 

One simple way to help remember the difference is that a.Equals(b) is more analogous to
a == (object)b.

The .Equals() method is not generic and accepts an argument of type "object", and so when comparing to the == operator you have to think about it as if the right-hand operand were cast to object first.

One implication is that a.Equals(b) will nearly always return some value for a and b, regardless of type (the normal way to overload is to just return false if b is an unkown type). a == b will just throw an exception if there's no comparison available for those types.

Joel Coehoorn