StringBuilder在ToString調用時緩存字符串嗎?例如,這將創建兩個不同的內存串,或只使用一個:是否StringBuilder在ToString()調用時緩存結果字符串?
var sb = new StringBuilder();
sb.Append("foo");
sb.Append("bar");
var str1 = sb.ToString();
var str2 = sb.ToString();
它會緩存連續讀取操作自己的結果呢?
StringBuilder在ToString調用時緩存字符串嗎?例如,這將創建兩個不同的內存串,或只使用一個:是否StringBuilder在ToString()調用時緩存結果字符串?
var sb = new StringBuilder();
sb.Append("foo");
sb.Append("bar");
var str1 = sb.ToString();
var str2 = sb.ToString();
它會緩存連續讀取操作自己的結果呢?
在source code尋找的StringBuilder
的ToString()
。答案是否
[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;
我想是因爲它的將是兩個可變和你在字符串生成器調用toString
var str1 = sb.ToString();//one variable and new string
var str2 = sb.ToString();//two variable and new string
我的意思是說每一次新的字符串將會被創建。
示例代碼:
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();
}
輸出:
foobar
foobar
foobar str1
foobar str2
完全相同實施的StringBuilder類是這樣的:
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;
}
,正如你可以看到它回報名爲RET是在這個方法內聲明的字符串....不被任何緩存...
str1和str2是「foo」和「bar」組合的2個單獨實例。當你第二次調用ToSring()時,第一次調用的時候會做同樣的事情,但這兩個調用之間沒有任何緩存,儘管我認爲它們可以。但是你也可以做str2 = str1。在這兩種情況下,str1和str2在不同的內存區域中都是2個獨立的不可變字符串。
兩個不同的字符串將在存儲在您的情況
var str1 = sb.ToString(); // 1st string
var str2 = sb.ToString(); // 2nd string
嗯創建,是什麼不清楚的嗎?這是簡單的緩存問題。 – eocron
但是爲什麼問,只需檢查'ReferenceEquals(str1,str2)' –
您還可以在類https://referencesource.microsoft.com/#mscorlib/system/text/stringbuilder中檢查「ToString」的實現。 cs – Pikoh