Search code examples
c#stringequalsstringbuilderequals-operator

Why does StringBuilder.Equals return "true" in this case?


I have a small issue comparing two StringBuilders in C# (XNA).

StringBuilder sb1;
StringBuilder sb2;

Both are initialized in different sections of my code. A simple Console.WriteLine shows that they contain the same text. However, the following is false:

sb1.Equals(sb2); // This is false

and yet the following is true

sb1.ToString().Equals(sb2.ToString); // This is true

How can this occur?


Solution

  • There are two overloads of Equals on StringBuilder which can do slightly unexpected things.

    The Equals(Object) overload is inherited from Object and compares references.

    The Equals(StringBuilder) overload compares content, Capacity, and MaxCapacity.

    You seem to be calling the second of these two overloads.

    Since StringBuilder will dynamically expand its capacity, the result of comparing two StringBuilder instances depends on the exact sequence of operations (e.g. Append, Replace, Remove, etc.) performed on each one.

    For example this give the result you describe:

    StringBuilder sb1 = new StringBuilder(), sb2 = new StringBuilder();
    sb1.Append("something").Append('1', 100).Replace("1", "");
    sb2.Append("something");
    Console.WriteLine(sb1.Equals(sb2)); // False
    Console.WriteLine(sb1.ToString().Equals(sb2.ToString())); // True
    

    There doesn't seem to be built-in way to only compare the content but you can easily write your own comparison if you don't want to allocate strings when comparing:

    public static bool Equals(StrinBuilder left, StringBuilder right)
    {
        if (left.Length != right.Length)
            return false;
    
        int length = left.Length;
        for(int i = 0; i < length; i++)
            if (left[i] != right[i])
                return false;
    
        return true;
    }