果然,这会将“01/01/2014”转换为“01012014”。但我的问题
是,替换是一步发生的,还是创建一个
中间字符串(例如:“0101/2014”或“01/012014”)?
No,它不会为每次替换创建中间字符串。但它确实创建了新的字符串,因为正如您所知,字符串是不可变的。
Why?
没有理由在每次替换时创建新字符串 - 避免它非常简单,并且它将带来巨大的性能提升。
如果你是很感兴趣, 参考source.microsoft.com http://referencesource.microsoft.com and SSCLI2.0 http://www.microsoft.com/en-gb/download/details.aspx?id=4917源代码将演示这一点(如何查看标记为 methodimploptions-internalcall 的方法代码 https://stackoverflow.com/questions/16579078/how-to-see-code-of-method-which-marked-as-methodimploptions-internalcall):
FCIMPL3(Object*, COMString::ReplaceString, StringObject* thisRefUNSAFE,
StringObject* oldValueUNSAFE, StringObject* newValueUNSAFE)
{
// unnecessary code ommited
while (((index=COMStringBuffer::LocalIndexOfString(thisBuffer,oldBuffer,
thisLength,oldLength,index))>-1) && (index<=endIndex-oldLength))
{
replaceIndex[replaceCount++] = index;
index+=oldLength;
}
if (replaceCount != 0)
{
//Calculate the new length of the string and ensure that we have
// sufficent room.
INT64 retValBuffLength = thisLength -
((oldLength - newLength) * (INT64)replaceCount);
gc.retValString = COMString::NewString((INT32)retValBuffLength);
// unnecessary code ommited
}
}
如你看到的,retValBuffLength
计算出来,就知道了数量replaceCount
's. The 真正的实施对于 .NET 4.0 可能有点不同(SSCLI 4.0 尚未发布),但我向你保证它不会做任何愚蠢的事情:-)。
我想知道是否有更好、更有效的替代方法
字符串中特定字符/子字符串的所有出现,即
不会另外创建字符串。
是的。可重复使用的StringBuilder
容量约为 2000 个字符。避免任何内存分配。仅当替换长度相等时,这才是正确的,并且如果处于紧密循环中,则可以获得不错的性能增益。
在编写任何内容之前,请使用大文件运行基准测试,看看性能是否足以满足您的需求。如果性能足够 - 则无需执行任何操作。