StringBuilder.Capacity
是否应设置为最大.NET字符数,而不考虑空终止,或者在使用P / Invoke时,必须将其设置为更高,以便为空终止符保留空间。
自然的反应是它应该设置得更高,但似乎P / Invoke应该自动补偿。事实上,这实际上是在这里记录的:http://msdn.microsoft.com/en-US/library/s9ts558h(v=VS.100).aspx
这个问题的原因是大多数例子与上述文件并不严格一致。它们几乎总是被编码:
StringBuilder sb = new StringBuilder(dotNetChars + 1);
SomeWindowsAPI(sb, sb.Capacity);
而不是:
StringBuilder sb = new StringBuilder(dotNetChars);
SomeWindowsAPI(sb, sb.Capacity + 1);
(我意识到一些API处理缓冲区大小参数的方式不同。假设API处理这种必须通用的方式,如GetFullPathName
:http://msdn.microsoft.com/en-us/library/aa364963(v=VS.85).aspx)
在API调用中直接使用带有sb.Capacity
的表达式似乎是避免不匹配的最佳做法。问题是添加+1是否正确。
环顾四周。您可能会发现显示sb.Capacity + 1
的唯一位置是MSDN文档。
当然,人们可以在谨慎的情况下使用比绝对必要的更大的缓冲区来分配,但我想知道如何做到这一点的共识。
答案 0 :(得分:4)
我已经意识到你已经有了五年的答案,但在我看来他们并没有真正回答这个问题,他们基本上没有检查这个潜在的问题,而没有检查这样做是否正确。
MSDN文档保证marshaller将确保有足够的空间来存储Capacity
的完整StringBuilder
以及额外的空终止符。引用Default Marshaling for Strings:
固定长度字符串缓冲区
[...]
解决方案是传递StringBuilder缓冲区作为参数而不是字符串。 StringBuilder 可以被被调用者取消引用和修改,前提是它不超过 StringBuilder 的容量。它也可以初始化为固定长度。例如,如果将 StringBuilder 缓冲区初始化为 N 的容量,则封送程序会提供大小为( N +1)个字符的缓冲区。 +1表示非托管字符串具有空终止符而 StringBuilder 不具有空终结符。
[...]
所以你不必担心增加一个容量,编组人员已经为你做了这个。
答案 1 :(得分:0)
在StringBuilder
的构造函数中,容量使用如下:
m_ChunkChars = new char[capacity];
这与m_ChunkLength
字段一起用于确定StringBuilder
的内容。这仅描述实际字符,不包括终止字符。
所以你的回答是没有必要+ 1
。
答案 2 :(得分:0)
可能有一定数量的货物崇拜节目正在进行中。当被问及为字符串分配的内存时,有人会回答习惯,即回答“长度+ 1”而不是长度。开发人员只是“在安全方面犯错误”并且传递长度为+1,而不是阅读有关为字符串分配内存的新情况的文档,而读取该代码的其他人推断出相同的规则和实践传播。从一个人传到另一个人,合理地可能是正确的,而不是有害的,不一定是正确的。