使用字符串初始化的 StringBuilder 是否恰好(仅)包含该字符串足够的空间?

发布于 2024-08-21 03:15:11 字数 1010 浏览 9 评论 0原文

我想知道这段代码是否......使用

StringBuilder sb = new StringBuilder("Please read the following messages.");

与传递给构造函数的字符串一样大的缓冲区初始化 sb 。一方面,这似乎是最合乎逻辑的事情。另一方面,它似乎违背了 StringBuilder 类最常见用途之一的目的,即提供可变性以使重复追加更加高效。 (如果我的问题的答案是“是”,则第一次调用 Append 时,将需要 sb 调整自身大小。)

话又说回来,我想人们可以查看此内容类似于以 IEnumerable 作为参数的 List 构造函数。也许本例中的假设是您不打算追加很多内容,而是操纵已经存在的内容。

我对此所做的唯一真正的研究是检查 StringBuilder 上的 MSDN 文档,它没有提供答案(它说构造函数“使用指定的字符串”初始化实例,但没有指示如何使用该字符串)。


编辑:所以它是“特定于实现的”......这对其他人来说不觉得奇怪吗?我的意思是,StringBuilder 类的目的是提供一种替代方法来对字符串执行大量操作,从而创建大量不可变的一路上的 string 实例;因此,这是为了效率。我觉得这个构造函数的行为应该被指定,以便开发人员可以做出明智的决定如何使用它,无论平台如何。

我的意思是,它是由微软以某种方式实现的;他们可以轻松地将其放入文档中(迫使其他实现也效仿)。只是个人的困惑......

I'm wondering if this code ...

StringBuilder sb = new StringBuilder("Please read the following messages.");

... initializes sb with a buffer exactly as large as the string passed to the constructor. On the one hand, this would seem the most logical thing. On the other hand, it seems to kind of defeat the purpose of the StringBuilder class for one of its most common uses, which is to provide mutability to make repeated appends more efficient. (The very first call to Append, if the answer to my question is "yes", would require sb to resize itself.)

Then again, I suppose one could view this as analogous to the constructor for List<T> that takes an IEnumerable<T> as a parameter. Maybe the assumption in this case is that you're not planning on appending a lot, but rather on manipulating what's already there.

The only real research I've done on this was to check the MSDN documentation on StringBuilder, which didn't provide an answer (it says the constructor initializes the instance "using the specified string," but doesn't indicate how the string is used).


EDIT: So it's "implementation-specific"... does this not seem weird to anyone else? I mean, the purpose of the StringBuilder class is to offer an alternative to performing a lot of operations on a string, creating a ton of immutable string instances along the way; therefore, it's for efficiency. I feel like the behavior of this constructor ought the be specified, so that the developer can make an informed decision how to use it regardless of platform.

I mean, it is implemented by Microsoft a certain way; they could easily have put that in the documentation (forcing other implementations to follow suit). Just a personal source of puzzlement...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

浸婚纱 2024-08-28 03:15:11

这是您无需担心的实现细节。但是,使用 .NET 反射器,并查看 (string,int32,int32, int32)构造函数的重载(其他构造函数调用),我们可以看到它选择的容量是 16 的倍数(请求大小的下一个最大)

编辑

实际上,它是 16 x 2 ^n,“n”的值被选为下一个最大的尺寸

It's an implementation detail that you shouldn't need to worry about. However, using .NET reflector, and looking in the (string,int32,int32,int32) overload of the constructor (which the other constructors call), we can see that it picks a capacity that is a multiple of 16 (next largest over the requested size)

Edit

Actually, it's 16 x 2^n, with the value of "n" selected to be the next largest size

南烟 2024-08-28 03:15:11

检查 StringBuilder 的Capacity成员。

来自 MSDN

StringBuilder 在需要时动态分配更多空间并相应增加容量。出于性能原因,StringBuilder 可能会分配比所需更多的内存。分配的内存量是特定于实现的。

Check the StringBuilder's Capacity member.

From MSDN:

The StringBuilder dynamically allocates more space when required and increases Capacity accordingly. For performance reasons, a StringBuilder might allocate more memory than needed. The amount of memory allocated is implementation-specific.

标点 2024-08-28 03:15:11

您链接到的构造函数可能链接到 StringBuilder(String, Int32, Int32, Int32)

public StringBuilder(
  string value,
  int startIndex,
  int length,
  int capacity
)

因此,对于字符串,它可能会传递: string, 0, string.Length, string。长度。或者在 StringBuilder 上下文中有意义的类似内容。

The constructor you linked to is probably chained to the StringBuilder(String, Int32, Int32, Int32):

public StringBuilder(
  string value,
  int startIndex,
  int length,
  int capacity
)

So, for the string, it would probably pass through: string, 0, string.Length, string.Length. Or something similar that makes sense in the StringBuilder context.

梦在夏天 2024-08-28 03:15:11

最终被调用的构造函数是:

// "Please read the following messages.".Length = 35
public StringBuilder(string value, int startIndex, int length, int capacity)
public StringBuilder("Please read the following messages.", 0, 
        "Please read the following messages.".Length, 16)

(这不是其他答案没有提供的,只是来自反射器)
如果容量小于字符串的长度(在这种情况下):

while (capacity < length)
{
    capacity *= 2;
    if (capacity < 0)
    {
        capacity = length;
        break;
    }
}

在 Mono 中,StringBuilder(string val) 构造函数将容量分配给 int.MaxValue,直到发生追加。

真正的答案在于最终在 CLR 内部调用的方法,其中长度是容量:

[MethodImpl(MethodImplOptions.InternalCall)]
private static extern string FastAllocateString(int length);

我在 SSCLI 但是 Mono 版本 (\mono\metadata\object.c) 是这样的:

mono_string_new_size (MonoDomain *domain, gint32 len)
{
    MonoString *s;
    MonoVTable *vtable;
    size_t size = (sizeof (MonoString) + ((len + 1) * 2));

...
}

大小是多少以 MonoString 对象的字节为单位,加上长度乘以 2。

The constructor that eventually gets called is:

// "Please read the following messages.".Length = 35
public StringBuilder(string value, int startIndex, int length, int capacity)
public StringBuilder("Please read the following messages.", 0, 
        "Please read the following messages.".Length, 16)

(This is nothing that the other answers don't provide, and is just from reflector)
If the capacity is less than the length of the string, which it is in this case:

while (capacity < length)
{
    capacity *= 2;
    if (capacity < 0)
    {
        capacity = length;
        break;
    }
}

In Mono, the StringBuilder(string val) constructor allocates the capacity to int.MaxValue until an append occurs.

The real answer lies in the method that ends up being called internally in the CLR, where length is the capacity:

[MethodImpl(MethodImplOptions.InternalCall)]
private static extern string FastAllocateString(int length);

I can't find the source for this in the SSCLI however the Mono version (\mono\metadata\object.c) does it like this:

mono_string_new_size (MonoDomain *domain, gint32 len)
{
    MonoString *s;
    MonoVTable *vtable;
    size_t size = (sizeof (MonoString) + ((len + 1) * 2));

...
}

Which is the size in bytes of a MonoString object, plus the length times 2.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文