In this following example the third evaluation returns false, all good, but the fourth example returns true..
I don't quite understand how this works however, by default Object.Equals
compares two references for object equality, and seeing as a
and b
both point to a unique instance of a string, this should return false, which it does in the third example but not in the fourth.
Now I understand why it returns true in the 2nd example seeing as the .Equals()
method is overridden in the string class, but in the fourth example we're casting this string as an object.
So wouldn't it call Object.Equals
in this case?
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); // Returns true
Console.WriteLine (a.Equals(b)); // Returns true
// 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); // Returns false
Console.WriteLine (c.Equals(d)); // Returns true
}
The clue is the words "by default". string
overrides object.Equals
with a custom implementation. Since object.Equals
is a polymorphic method (virtual
/ override
/ etc), the most-derived implementation gets used even if the variable (/expression) type is object
.
==
, however, is not polymorphic; the implementation used depends entirely on the variable (/expression) type. In this case, since the known type is object
, the only comparison available is reference equality.
Perhaps more succinctly:
class Foo {
public override string ToString() { return "hi"; }
}
//...
object obj = new Foo();
string s = obj.ToString(); // this is "hi"
This is the same principle: the most derived overload of a virtual method is used, regardless of the type that the compiler knows about (object
in this case).