c# - 在不调用 ToString().Trim() 的情况下从 StringBuilder 的末尾修剪空格并返回到新的 SB

标签 c# stringbuilder

什么是在不调用 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;
}

注意事项:

  1. 如果为 Null 或 Empty,则返回。

  2. 如果实际上不需要 Trim,我们说的是返回时间非常快,最昂贵的调用可能是对 char.IsWhiteSpace 的单次调用。因此,在不需要时调用 TrimEnd 几乎为零,而不是这些 ToString().Trim() 返回 SB 路由。

  3. 否则,如果需要修剪,最昂贵的事情是多次调用 char.IsWhiteSpace (在第一个非空白字符处中断)。当然,循环向后迭代;如果所有的都是空格,你将得到一个 SB.Length 为 0 的结果。

  4. 如果遇到空格,i 索引将保留在循环之外,这样我们就可以用它适本地削减长度。在 StringBuilder 中,这是令人难以置信的性能,它只是设置一个内部长度整数(内部 char[] 保持相同的内部长度)。

更新:参见 Ryan Emerle 的精彩笔记如下,它纠正了我的一些误解(SB 的内部工作比我想象的要复杂一些):

The StringBuilder is technically a linked list of blocks of char[] 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/

相关文章:

c# - 如何 "Snoop"一个上下文菜单?

c# - 使用 Timer 了解对象的年龄

java - 为什么Java中不捕获返回值可以?

c# - String 或 StringBuilder 返回值?

c# - 'method' 没有重载匹配委托(delegate) 'System.EventHandler'

c# - SqlDataAdapter、SqlCommand 从字符串中删除前导数字

c# - 字符串返回字节数组 - 不工作

c# - 如何切片/修剪这个值?

java - 如何向 stringbuilder 添加另一个字符串?

c# - Reverse String.Replace - 更快的方法?