Pritam Karmakar
Pritam Karmakar

Reputation: 2801

Why object.Equals and instanceobject.Equals are not same

        string s1 = "t";
        string s2 = 't'.ToString();        

        Console.WriteLine(s1.Equals(s2)); // returning true
        Console.WriteLine(object.Equals(s1, s2)); // returning true

Here it is returning same result. Now when I'm using StringBuilder it is not returning same value. What is the underneath reason?

        StringBuilder s1 = new StringBuilder();
        StringBuilder s2 = new StringBuilder();

        Console.WriteLine(s1.Equals(s2)); // returning true
        Console.WriteLine(object.Equals(s1, s2)); // returning false

Edit1: My above question answered below. But during this discussion what we find out StringBuilder doesn't have any override Equals method in its implementation. So when we call StringBuilder.Equals it actually goes to Object.Equals. So if someone calls StringBuilder.Equals and S1.Equals(S2) the result will be different.

Upvotes: 8

Views: 351

Answers (3)

Matt
Matt

Reputation: 14541

The generic Equals method compares the references of two objects to see if they have reference equality for reference types such as StringBuilder. For values types, and string behaves like a value type (is immutable), it does a bitwise comparison (determines if the binary representation is the same). This functionality, however, is overloaded in the StringBuilder class.

According to MSDN, the StringBuilder's equal method will return true if the following criteria for both StringBuilder objects are equal:

  • String
  • Capacity
  • MaxCapacity

Thus, s1 and s2 in the second example fail reference equality, but pass the custom StringBuilder Equals equality based on the criteria just mentioned.

Upvotes: 1

Eric J.
Eric J.

Reputation: 150148

String.Equals() is overriden in C# such that identical strings are in fact Equal() when the Equal() override defined on string is used.

If you are comparing string literals (not the case in your example), it's worth noting that identical string literals are interned... that is, identical strings live at the same address so will also be equal by reference (e.g. object.Equals() or s1.ReferenceEquals(s2)) as well as by value.

StringBuilder provides an overload to Equals() that takes StringBuilder as a parameter (that is s1.Equals(s2) will call that overload instead of calling object.Equals(object obj)).

http://msdn.microsoft.com/en-us/library/system.text.stringbuilder.equals.aspx

StringBuilder.Equals() is...

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

object.Equals() uses the static Equals() defined on object, which checks only for reference equality (if passed a class) or for value equality (if passed a struct).

So in summary

string s1 = "t";
string s2 = 't'.ToString();        

Console.WriteLine(s1.Equals(s2)); // true because both reference equality (interned strings) and value equality (string overrides Equals())
Console.WriteLine(object.Equals(s1, s2)); // true because of reference equality (interned strings)

StringBuilder s1 = new StringBuilder();
StringBuilder s2 = new StringBuilder();

Console.WriteLine(s1.Equals(s2)); // true because StringBuilder.Equals() overloaded
Console.WriteLine(object.Equals(s1, s2)); // false because the two StringBuilder instances have different addresses (references not equal)

Upvotes: 7

competent_tech
competent_tech

Reputation: 44941

The string class implements Equals in such a way that it compares the values of the strings.

Most object instances, unless they implement a different type of comparison, check to see whether or not the object references are the same.

Note that there is also a case where two different string constants that contain the exact same value are initially assigned to the same object reference by the compiler.

Upvotes: 1

Related Questions