26

I have a question about Object.Equals and Equals(object). My sample code is below:

class Program
{
    static void Main(string[] args)
    {
        var sb1 = new StringBuilder("Food");
        var sb2 = new StringBuilder("Food");
        Console.WriteLine(sb1 == sb2);
        Console.WriteLine(sb1.Equals(sb2));
        Console.WriteLine(Object.Equals(sb1, sb2));
        Console.WriteLine(Object.ReferenceEquals(sb1, sb2));
        Console.ReadLine();
    }
}

The output is:

False
True
False
False

But as far as I'm concerned Object.Equals(sb1, sb2) internally calls sb1.Equals(sb2) so why does it give two different results?

M.A.R.
  • 159
  • 1
  • 7
  • 14
amitabha
  • 646
  • 1
  • 9
  • 20
  • You should come up with a better question title. The current doesn't mean anything. Please don't repeat tags in titles. – Ondrej Tucny May 05 '13 at 09:20
  • @ReferenceEquals: You are compare four methods of comparison. I modified your title to reflect your question a little better. – Martin Mulder May 05 '13 at 09:36
  • 3
    Why are you checking for equality on 2 stringbuilders? It is like checking a stream or textwriter for equality. – leppie May 05 '13 at 09:57

3 Answers3

18

You are missing another test:

Console.WriteLine(sb1.Equals((object)sb2)); // False!

StringBuilder does not override Equals(object), it overloads it with another Equals(StringBuilder).

Object.Equals(object, object) is calling Equals(object), so the result is false.

Kobi
  • 135,331
  • 41
  • 252
  • 292
  • Overloading `Equals` without overriding it. WTF did they think. Personally I would have used reference equality, but this choice is just confusing. – CodesInChaos May 05 '13 at 09:18
  • 1
    You should explain about the difference between [`Object.Equals()`](http://msdn.microsoft.com/en-us/library/bsc2ak47.aspx) and [`IEquatable`](http://msdn.microsoft.com/en-us/library/ms131187.aspx) – Matthew Watson May 05 '13 at 09:20
  • Because we have two different references (objects, instances) and default Equal(object) should return reference comparison first. – Uzzy May 05 '13 at 09:22
  • 1
    @MatthewWatson - I don't think StringBuild implements `IEquatable`: http://msdn.microsoft.com/en-us/library/system.text.stringbuilder.aspx – Kobi May 05 '13 at 09:22
  • @Kobi Yep, although it *does* have something that would match it. Weird that they didn't add the interface. Probably it would have been a breaking change. – Matthew Watson May 05 '13 at 09:27
  • From your link: **It determines whether the two objects represent the same object reference. If they do, the method returns true.** This test is equivalent to calling the ReferenceEquals method. In addition, if both objA and objB are null, the method returns true. – Uzzy May 05 '13 at 09:30
  • @Uzzy - But what happens when the references are not equal? After null checks, it calls an overridden `.Equals(object)`, which may do anything. I don't think I understand exactly what you are saying, by the way. Is my answer wrong? – Kobi May 05 '13 at 09:44
  • @Kobi - answer is right, my comment was addressed to CodesInChaos. I am sorry for inconvenience – Uzzy May 05 '13 at 09:48
  • @Kobi `sb1.Equals(sb2)` calls `StringBuilder.Equals`, `sb1.Equals((object)sb2)` calls `Object.Equals`. Your answer looks right to me.. – Soner Gönül May 05 '13 at 09:55
  • @MatthewWatson `IEquatable` needs to equivalent to `object.Equals` (and consistent with `GetHashCode`). AFAIK it is mainly a performance optimization to avoid boxing on value types. – CodesInChaos May 05 '13 at 09:57
4

You are using 4 different methods of comparison, result in different results:

  • Operator == will by default do a check if the references are equal. In this case you have two instances, so they do have two different references. The behavior of == can overridden by any type (like string has its own method of comparison), but in case of the StringBuilder it is not.
  • Method StringBuilder.Equals(StringBuilder) will compare with another StringBuilder and compares some inside values. These values are, in your case, the same. Strange thing is that StringBuilder does not override the method StringBuilder.Equals(object) to apply the same logic.
  • Method object.Equals(object, object) will try to call the method .Equals(object) of one of the objects. In this case: StringBuilder.Equals(object) which, as I said, did not have the logic to compare the values. Resulting in just a compare of the references of both instances.
  • Object.ReferenceEquals will just compare the references.

For more info, see:

Martin Mulder
  • 12,642
  • 3
  • 25
  • 54
3

StringBuilder.equals does not compare the objects but rather from MSDN:

"True if this instance and sb have equal string, Capacity, and MaxCapacity values; otherwise, false."

The rest of the checks you're doing compare the reference.

E.T.
  • 949
  • 8
  • 21