Reputation: 7526
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
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
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
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
Reputation: 48258
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
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