从StringBuilder的末尾修剪空格而不调用ToString().修剪()并返回到新的SB

Nic*_*sen 23 c# stringbuilder

StringBuilder没有调用ToString()的情况下从空尾修剪空白的有效方法是什么.修剪()并返回到新的SB new StringBuilder(sb.ToString().Trim()).

Nic*_*sen 40

以下是扩展方法,因此您可以这样调用它:

    sb.TrimEnd();
Run Code Online (Sandbox Code Playgroud)

此外,它返回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;
    }
Run Code Online (Sandbox Code Playgroud)

笔记:

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

2)如果实际上不需要Trim,我们正在谈论一个非常快速的返回时间,可能最昂贵的调用是对char.IsWhiteSpace的单次调用.所以在不需要时调用TrimEnd实际上是零费用,而不是这些ToString().Trim()返回SB路由.

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

4)如果遇到空格,则i索引保持在循环之外,这允许我们适当地剪切长度.在StringBuilder中,这是非常高效的,它只是设置一个内部长度整数(内部char []保持相同的内部长度).

UPDATE2:看看Ryan Emerle的优秀笔记如下,这些笔记纠正了我的一些误解(SB的内部工作比我做的要复杂得多):

StringBuilder在技术上是char []块的链接列表,所以我们不会在LOH中结束.调整长度在技术上并不像更改结束索引那么简单,因为如果移动到不同的块中,则必须维护容量,因此可能需要分配新的块.不过,你只在最后设置了Length属性,所以这似乎是一个很好的解决方案.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 
Run Code Online (Sandbox Code Playgroud)

在更改Length之后,您可以看到内部数组(m_​​ChunkChars)保持相同的大小,事实上,您可以在调试器中看到它甚至不会覆盖(在这种情况下为空白)字符.他们是孤儿.

  • 从技术上讲,“StringBuilder”是“char[]”块的链接列表,因此我们不会最终陷入[LOH](http://msdn.microsoft.com/en-us/magazine/cc534993.aspx) 。从技术上来说,调整长度并不像更改结束索引那么简单,因为如果移动到不同的块,则必须维护“容量”,因此可能需要分配新的块。尽管如此,您只在最后设置“Length”属性,所以这似乎是一个很好的解决方案。 (2认同)
  • 我们在序列化 270 MB JSON 字符串时遇到问题。切换到此方法后,发布版本所需的时间从 22 分钟变为 12 秒。 (2认同)