eocron
eocron

Reputation: 7526

Does StringBuilder cache the resulting string upon ToString() call?

Does StringBuilder cache the string upon ToString call? For example, will this create two different in-memory strings, or use just one:

var sb = new StringBuilder();
sb.Append("foo");
sb.Append("bar");

var str1 = sb.ToString();
var str2 = sb.ToString();

Will it cache its own result for consecutive read operations?

Upvotes: 4

Views: 915

Answers (5)

pankaj kumar singh
pankaj kumar singh

Reputation: 17

Two different string will create in the memory in your case

var str1 = sb.ToString(); // 1st string    
var str2 = sb.ToString(); // 2nd string

Upvotes: -1

user734028
user734028

Reputation: 1111

str1 and str2 are 2 separate instances of "foo" and "bar" combined. The ToSring() first called does the same thing when you call it the second time, nothing is cached in between those 2 calls, although I think they could have. But then you could also have done str2 = str1. In both cases str1 and str2 are 2 separate immutable strings in difference memory areas.

Upvotes: 0

David Pilkington
David Pilkington

Reputation: 13620

Looking at the source code for the ToString() of StringBuilder. The answer is No

    [System.Security.SecuritySafeCritical]  // auto-generated
    public override String ToString() {
        Contract.Ensures(Contract.Result<String>() != null);

        VerifyClassInvariant();

        if (Length == 0)
            return String.Empty;

        string ret = string.FastAllocateString(Length);
        StringBuilder chunk = this;
        unsafe {
            fixed (char* destinationPtr = ret)
            {
                do
                {
                    if (chunk.m_ChunkLength > 0)
                    {
                        // Copy these into local variables so that they are stable even in the presence of ----s (hackers might do this)
                        char[] sourceArray = chunk.m_ChunkChars;
                        int chunkOffset = chunk.m_ChunkOffset;
                        int chunkLength = chunk.m_ChunkLength;

                        // Check that we will not overrun our boundaries. 
                        if ((uint)(chunkLength + chunkOffset) <= ret.Length && (uint)chunkLength <= (uint)sourceArray.Length)
                        {
                            fixed (char* sourcePtr = sourceArray)
                                string.wstrcpy(destinationPtr + chunkOffset, sourcePtr, chunkLength);
                        }
                        else
                        {
                            throw new ArgumentOutOfRangeException("chunkLength", Environment.GetResourceString("ArgumentOutOfRange_Index"));
                        }
                    }
                    chunk = chunk.m_ChunkPrevious;
                } while (chunk != null);
            }
        }
        return ret;

Upvotes: 8

the exactly implementation of the StringBuilder class is this:

public override String ToString()
{
    Contract.Ensures(Contract.Result<String>() != null);

    VerifyClassInvariant();

    if (Length == 0)
        return String.Empty;

    string ret = string.FastAllocateString(Length);
    StringBuilder chunk = this;
    unsafe
    {
        fixed (char* destinationPtr = ret)
        {
            do
            {
                if (chunk.m_ChunkLength > 0)
                {
                    // Copy these into local variables so that they are stable even in the presence of ----s (hackers might do this)
                    char[] sourceArray = chunk.m_ChunkChars;
                    int chunkOffset = chunk.m_ChunkOffset;
                    int chunkLength = chunk.m_ChunkLength;

                    // Check that we will not overrun our boundaries. 
                    if ((uint)(chunkLength + chunkOffset) <= ret.Length && (uint)chunkLength <= (uint)sourceArray.Length)
                    {
                        fixed (char* sourcePtr = sourceArray)
                            string.wstrcpy(destinationPtr + chunkOffset, sourcePtr, chunkLength);
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException("chunkLength", Environment.GetResourceString("ArgumentOutOfRange_Index"));
                    }
                }
                chunk = chunk.m_ChunkPrevious;
            } while (chunk != null);
        }
    }
    return ret;
}

and as you can see it returns a string with the name ret that is declared inside of that method.... is not cached anywhere...

Upvotes: 2

Pranay Rana
Pranay Rana

Reputation: 176896

I think yes as its going to be two variable and you are calling tostring on string builder

var str1 = sb.ToString();//one variable and new string
var str2 = sb.ToString();//two variable and new string 

i mean to say every time new string will get created.

Example code :

static void Main(string[] args)
        {

            var sb = new StringBuilder();
            sb.Append("foo");
            sb.Append("bar");

            var str1 = sb.ToString();
            var str2 = sb.ToString();

            Console.WriteLine(str1);
            Console.WriteLine(str2);
            str1 += " str1";
            str2 += " str2";

            Console.WriteLine(str1);
            Console.WriteLine(str2);

            Console.ReadLine();
        }

output :

foobar
foobar
foobar str1
foobar str2

Upvotes: 0

Related Questions