是否应该将 StringBuilder.Capacity
设置为 .NET 字符的最大数量,而不考虑 null 终止符,或者必须将其设置得更高,以便在使用 P/Invoke 时为 null 终止符保留空间.
自然 react 是应该将其设置得更高,但似乎 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 文档。
当然,为了谨慎起见,可以分配比严格必要的更大的缓冲区,但我想知道如何做到这一点的共识。
最佳答案
我意识到你已经有五年前的答案了,但在我看来,它们并没有真正回答问题,它们基本上忽略了潜在的问题,而没有检查这样做是否正确。
MSDN 文档保证编码器将确保有足够的空间来存储 StringBuilder
的全部 Capacity
以及额外的 null 终止符。引用Default Marshaling for Strings :
Fixed-Length String Buffers
[...]
The solution is to pass a StringBuilder buffer as the argument instead of a string. A StringBuilder can be dereferenced and modified by the callee, provided it does not exceed the capacity of the StringBuilder. It can also be initialized to a fixed length. For example, if you initialize a StringBuilder buffer to a capacity of N, the marshaler provides a buffer of size (N+1) characters. The +1 accounts for the fact that the unmanaged string has a null terminator while StringBuilder does not.
[...]
因此,您不必担心向容量添加 1,编码器已经为您完成此操作。
关于.net - 使用 P/Invoke 时设置 StringBuilder.Capacity 的正确方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4057007/