none
Is this StringBuilder and this String equal? RRS feed

  • Question

  • So I have a StringBuilder variable and a string variable.

     

    I simply want to know whether the contents of the StringBuilder and the string are equal.

    However, I've been looking into how a StringBuilder works and when it is converted back into a string a duplicate copy of the contents is created.

    Isn't that a problem with performance when the strings have a couple megabytes worth of characters in them?

     

    Is there a better way to compare these two? Or is the only way to call StringBuilder.ToString() and then compare?

    Thursday, October 21, 2010 10:53 PM

Answers

  • > Or is the only way to call StringBuilder.ToString() and then compare?

    Unfortunately, Microsoft did not go so far as to ensure that StringBuilder is a superset of the methods of String.  Too bad.  I don't really know the answer as to whether you can beat ToString's performance in this case.  You can certainly compare char by char, but I wouldn't be surprised if that ends up slower than using ToString.  An improvement on the char by char would be to use CopyTo to copy it and compare by chunks into a temporary buffer a few KB big.  If the strings are different, chances are you will be able to break early without even running the whole string to this buffer.  I know I really haven't answered your quesetion, but I did want to chime in and say that I too am disappointed with the set of methods implemented by StringBuilder.  Note to self to check on connect.microsoft.com sometime and see if anyone has suggested improving StringBuilder to be more like String.

    Note that the character comparison approaches, including the buffered one, will get complicated if you need a non-ordinal comparison (for various language stuff).  If you just trying to reproduce StringComparison.Ordinal mode, then it should be straightforward.

    • Marked as answer by John Schewe Friday, October 22, 2010 1:16 AM
    Friday, October 22, 2010 12:32 AM
  • Thanks guys for the help, it's sad that Microsoft didn't make StringBuilder more versatile.


    I realize that I could enumerate through each char and there by maybe save a little memory, however after creating a program and performing a timed comparison the results were obvious at the extremes:

    1. Using a string with: 25000 chars, results from 100 tests:
      Using StringBuilder.ToString(): Min 0ms, Avg 0.00000ms, Max 0ms
      Using StringBuilderContentsEqualsString: Min 0ms, Avg 0.00000ms, Max 0ms
    2. Using a string with: 1000000 chars, results from 100 tests:
      Using StringBuilder.ToString(): Min 2ms, Avg 2.26000ms, Max 4ms
      Using StringBuilderContentsEqualsString: Min 197ms, Avg 198.58000ms, Max 209ms
    3. Using a string with: 100000000 chars, results from 2 tests:
      Using StringBuilder.ToString(): Min 252ms, Avg 259.50000ms, Max 267ms
      Using StringBuilderContentsEqualsString: Interrupted (More than 3 minutes on first test)

    I guess I'll just have to use the ToString method after all.

    • Marked as answer by John Schewe Friday, October 22, 2010 2:19 AM
    Friday, October 22, 2010 2:17 AM

All replies

  • > Or is the only way to call StringBuilder.ToString() and then compare?

    Unfortunately, Microsoft did not go so far as to ensure that StringBuilder is a superset of the methods of String.  Too bad.  I don't really know the answer as to whether you can beat ToString's performance in this case.  You can certainly compare char by char, but I wouldn't be surprised if that ends up slower than using ToString.  An improvement on the char by char would be to use CopyTo to copy it and compare by chunks into a temporary buffer a few KB big.  If the strings are different, chances are you will be able to break early without even running the whole string to this buffer.  I know I really haven't answered your quesetion, but I did want to chime in and say that I too am disappointed with the set of methods implemented by StringBuilder.  Note to self to check on connect.microsoft.com sometime and see if anyone has suggested improving StringBuilder to be more like String.

    Note that the character comparison approaches, including the buffered one, will get complicated if you need a non-ordinal comparison (for various language stuff).  If you just trying to reproduce StringComparison.Ordinal mode, then it should be straightforward.

    • Marked as answer by John Schewe Friday, October 22, 2010 1:16 AM
    Friday, October 22, 2010 12:32 AM
  • There is no direct way to compare them.  However, you could write your own method to do it without large memory overhead:

    bool StringBuilderContentsEqualsString(StringBuilder sb, string compare)
    {
      // Check the easiest one up front...
      if (sb.Length != compare.Length)
        return false;
    
      for (i=0;i<sb.Length;++i)
      {
        if (sb[i] != compare[i])
          return false;
      }
    
      return true;
    }

    Unfortunately, since StringBuilder doesn't implement IEnumerable<Char>, there really isn't a way to do it with LINQ more elegantly, unless you want to make a secondary method:

     

    // Given an extension like this...
    public static class StringBuilderExtensions
    {
      IEnumerable<char> Enumerate(this StringBuilder sb)
      {
         for(int i=0;i<sb.Length;++i)
            yield return sb[i];
      }
    }
    
    // You could do:
    
    bool equal = sb.Length==compare.Length && 
              sb.Enumerate().Zip(compare, (c1, c2) => c1 == c2).All();
    


    Reed Copsey, Jr. - http://reedcopsey.com
    If a post answers your question, please click "Mark As Answer" on that post and "Mark as Helpful".
    Friday, October 22, 2010 12:37 AM
    Moderator
  • Thanks guys for the help, it's sad that Microsoft didn't make StringBuilder more versatile.


    I realize that I could enumerate through each char and there by maybe save a little memory, however after creating a program and performing a timed comparison the results were obvious at the extremes:

    1. Using a string with: 25000 chars, results from 100 tests:
      Using StringBuilder.ToString(): Min 0ms, Avg 0.00000ms, Max 0ms
      Using StringBuilderContentsEqualsString: Min 0ms, Avg 0.00000ms, Max 0ms
    2. Using a string with: 1000000 chars, results from 100 tests:
      Using StringBuilder.ToString(): Min 2ms, Avg 2.26000ms, Max 4ms
      Using StringBuilderContentsEqualsString: Min 197ms, Avg 198.58000ms, Max 209ms
    3. Using a string with: 100000000 chars, results from 2 tests:
      Using StringBuilder.ToString(): Min 252ms, Avg 259.50000ms, Max 267ms
      Using StringBuilderContentsEqualsString: Interrupted (More than 3 minutes on first test)

    I guess I'll just have to use the ToString method after all.

    • Marked as answer by John Schewe Friday, October 22, 2010 2:19 AM
    Friday, October 22, 2010 2:17 AM