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