InplaceStringBuilder 和 StringBuilder 有什么区别?
Whats the difference between InplaceStringBuilder and StringBuilder?
今天,当我尝试输入 StringBuilder
时,VS2017 智能感知出现 InplaceStringBuilder
。 InplaceStringBuilder
对我来说是新手,所以我开始挖掘,看看我能学到什么。
我注意到的第一件事是它是一个结构而不是 class 并且它的类型信息如下所示:
#region Assembly Microsoft.Extensions.Primitives, Version=1.1.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60
// C:\Users\Ron Clabo\Documents\Visual Studio 2017\Projects\wwwGiftOasisResponsive\packages\Microsoft.Extensions.Primitives.1.1.0\lib\netstandard1.0\Microsoft.Extensions.Primitives.dll
#endregion
using System.Diagnostics;
namespace Microsoft.Extensions.Primitives {
[DebuggerDisplay("Value = {_value}")]
public struct InplaceStringBuilder {
public InplaceStringBuilder(int capacity);
public int Capacity { get; set; }
public void Append(string s);
public void Append(char c);
public override string ToString();
}
}
所以它的方法比StringBuilder
少很多。然后我四处搜索以了解有关 InplaceStringBuilder
的更多信息,但网络上还没有太多关于它的信息,所以它看起来很新。
另外,区别我已经说了,InplaceStringBuilder
和StringBuilder
有什么区别;开发人员什么时候应该使用新的 InplaceStringBuilder
而不是旧的 StringBuilder
?
当生成的字符串比初始容量长时,正常的StringBuilder
增加容量。 InplaceStringBuilder
受其容量限制,如果结果字符串较长,则会抛出异常。
这是InplaceStringBuilder
的一个很大的限制,所以它可能只适用于极少数情况。此外,如果您提前知道容量,则已经可以定义普通StringBuilder
.
的初始容量
来源:查看 InplaceStringBuilder
在 GitHub and compare to StringBuilder
on MSDN
上的实施
因为它只进行一次分配,所以 InplaceStringBuilder
对于众所周知的、大小合理的字符串更有效。我们可能希望在需要非常高效的方法中使用它。
它是在 pull request #157 中引入的,其中包括以下评论。
Intended to be used instead of pooled StringBuilder
or string.Concat
when all parts of string are known... Does only 1 allocation of resulting string... should only be used for well-known reasonably sized strings. For everything else, use StringBuilder
... do not use across await points...
PR 的历史讲述了这个故事:
- 2016 年 7 月,Issue #676 注意到不必要的分配。
- 2016 年 9 月,Pull request #699 解决了问题 #676 并建议分解出 "inplace string formatting into a struct..."
- 2016 年 9 月,Issue #717 正式确定提案。
- 2016 年 9 月,Pull request #157 实施提案。
InplaceStringBuilder
是一种通过附加块来构建字符串的非常快速的方法,前提是您事先知道最终字符串的长度。它的工作原理是预先分配一个固定大小的 string
,然后 改变 该字符串(不安全地,通过指针),因为您将块附加到构建器。当你调用 ToString
时,预先分配的字符串,现在充满了数据,直接返回而不需要复制。 (StringBuilder
在您调用 ToString
时复制其内容。)
字符串通常是不可变的,因此您最好确保不要在调用 ToString
之后调用 Append
来改变字符串。 InplaceStringBuilder
试图通过仅允许追加(您不能倒回并写入已追加的字符串的一部分)并要求您在调用 ToString
之前填充整个字符串来确保安全.
然而,InplaceStringBuilder
是一个可变结构,这意味着它通过复制传递。如果您复制构建器(例如,通过将其作为参数传递),副本可能会与原始文件不同步。具体来说,副本的 _offset
字段跟踪到目前为止已附加了多少个字符(以便知道在何处写入下一个 Append
调用),它可能指的是字符串中的某个位置原著已经写好了
也就是说,InplaceStringBuilder
不安全并且使用起来有风险。如果处理不当,您可能会破坏 string
最重要的属性之一,即不变性。确保您知道自己在做什么!
今天,当我尝试输入 StringBuilder
时,VS2017 智能感知出现 InplaceStringBuilder
。 InplaceStringBuilder
对我来说是新手,所以我开始挖掘,看看我能学到什么。
我注意到的第一件事是它是一个结构而不是 class 并且它的类型信息如下所示:
#region Assembly Microsoft.Extensions.Primitives, Version=1.1.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60
// C:\Users\Ron Clabo\Documents\Visual Studio 2017\Projects\wwwGiftOasisResponsive\packages\Microsoft.Extensions.Primitives.1.1.0\lib\netstandard1.0\Microsoft.Extensions.Primitives.dll
#endregion
using System.Diagnostics;
namespace Microsoft.Extensions.Primitives {
[DebuggerDisplay("Value = {_value}")]
public struct InplaceStringBuilder {
public InplaceStringBuilder(int capacity);
public int Capacity { get; set; }
public void Append(string s);
public void Append(char c);
public override string ToString();
}
}
所以它的方法比StringBuilder
少很多。然后我四处搜索以了解有关 InplaceStringBuilder
的更多信息,但网络上还没有太多关于它的信息,所以它看起来很新。
另外,区别我已经说了,InplaceStringBuilder
和StringBuilder
有什么区别;开发人员什么时候应该使用新的 InplaceStringBuilder
而不是旧的 StringBuilder
?
当生成的字符串比初始容量长时,正常的StringBuilder
增加容量。 InplaceStringBuilder
受其容量限制,如果结果字符串较长,则会抛出异常。
这是InplaceStringBuilder
的一个很大的限制,所以它可能只适用于极少数情况。此外,如果您提前知道容量,则已经可以定义普通StringBuilder
.
来源:查看 InplaceStringBuilder
在 GitHub and compare to StringBuilder
on MSDN
因为它只进行一次分配,所以 InplaceStringBuilder
对于众所周知的、大小合理的字符串更有效。我们可能希望在需要非常高效的方法中使用它。
它是在 pull request #157 中引入的,其中包括以下评论。
Intended to be used instead of pooled
StringBuilder
orstring.Concat
when all parts of string are known... Does only 1 allocation of resulting string... should only be used for well-known reasonably sized strings. For everything else, useStringBuilder
... do not use across await points...
PR 的历史讲述了这个故事:
- 2016 年 7 月,Issue #676 注意到不必要的分配。
- 2016 年 9 月,Pull request #699 解决了问题 #676 并建议分解出 "inplace string formatting into a struct..."
- 2016 年 9 月,Issue #717 正式确定提案。
- 2016 年 9 月,Pull request #157 实施提案。
InplaceStringBuilder
是一种通过附加块来构建字符串的非常快速的方法,前提是您事先知道最终字符串的长度。它的工作原理是预先分配一个固定大小的 string
,然后 改变 该字符串(不安全地,通过指针),因为您将块附加到构建器。当你调用 ToString
时,预先分配的字符串,现在充满了数据,直接返回而不需要复制。 (StringBuilder
在您调用 ToString
时复制其内容。)
字符串通常是不可变的,因此您最好确保不要在调用 ToString
之后调用 Append
来改变字符串。 InplaceStringBuilder
试图通过仅允许追加(您不能倒回并写入已追加的字符串的一部分)并要求您在调用 ToString
之前填充整个字符串来确保安全.
然而,InplaceStringBuilder
是一个可变结构,这意味着它通过复制传递。如果您复制构建器(例如,通过将其作为参数传递),副本可能会与原始文件不同步。具体来说,副本的 _offset
字段跟踪到目前为止已附加了多少个字符(以便知道在何处写入下一个 Append
调用),它可能指的是字符串中的某个位置原著已经写好了
也就是说,InplaceStringBuilder
不安全并且使用起来有风险。如果处理不当,您可能会破坏 string
最重要的属性之一,即不变性。确保您知道自己在做什么!