什么是在不调用 ToString().Trim() 的情况下从 StringBuilder
的末尾修剪空白并返回到新的 SB new StringBuilder(sb.ToString() .Trim())
。
最佳答案
下面是一个扩展方法,可以这样调用:
sb.TrimEnd();
此外,它还返回 SB 实例,允许您链接其他调用 (sb.TrimEnd().AppendLine()
)。
public static StringBuilder TrimEnd(this StringBuilder sb)
{
if (sb == null || sb.Length == 0) return sb;
int i = sb.Length - 1;
for (; i >= 0; i--)
if (!char.IsWhiteSpace(sb[i]))
break;
if (i < sb.Length - 1)
sb.Length = i + 1;
return sb;
}
注意事项:
如果为 Null 或 Empty,则返回。
如果实际上不需要 Trim,我们说的是返回时间非常快,最昂贵的调用可能是对
char.IsWhiteSpace
的单次调用。因此,在不需要时调用TrimEnd
几乎为零,而不是这些ToString().Trim()
返回 SB 路由。否则,如果需要修剪,最昂贵的事情是多次调用
char.IsWhiteSpace
(在第一个非空白字符处中断)。当然,循环向后迭代;如果所有的都是空格,你将得到一个SB.Length
为 0 的结果。如果遇到空格,
i
索引将保留在循环之外,这样我们就可以用它适本地削减长度。在StringBuilder
中,这是令人难以置信的性能,它只是设置一个内部长度整数(内部char[]
保持相同的内部长度)。
更新:参见 Ryan Emerle 的精彩笔记如下,它纠正了我的一些误解(SB 的内部工作比我想象的要复杂一些):
The
StringBuilder
is technically a linked list of blocks ofchar[]
so we don't end up in the LOH. Adjusting the length isn't technically as simple as changing the end index because if you move into a different chunk the Capacity must be maintained, so a new chunk may need to be allocated. Nevertheless, you only set the Length property at the end, so this seems like a great solution. Relevant details from Eric Lippert: https://stackoverflow.com/a/6524401/62195
另请参阅这篇讨论 .NET 4.0 新 StringBuilder
实现的好文章:http://1024strongoxen.blogspot.com/2010/02/net-40-stringbuilder-implementation.html
更新:下面说明了当 StringBuilder
长度改变时会发生什么(这里对 SB 进行的唯一实际操作,并且仅在需要时才进行):
StringBuilder sb = new StringBuilder("cool \t \r\n ");
sb.Capacity.Print(); // 16
sb.Length.Print(); // 11
sb.TrimEnd();
sb.Capacity.Print(); // 16
sb.Length.Print(); // 4
您可以看到内部数组 (m_ChunkChars
) 在更改长度后保持相同大小,事实上,您可以在调试器中看到它甚至没有覆盖(在本例中为空格) 人物。他们都是孤儿。
关于c# - 在不调用 ToString().Trim() 的情况下从 StringBuilder 的末尾修剪空格并返回到新的 SB,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24769701/