我需要整理几个字符串。我正在使用StringBuilder,如下所示
StringBuilder result = new StringBuilder(length);
长度是"长度"我最后想要的字符串。
"长度"是更高的数字。 要获得我需要做的字符串
return result.ToString();
当我试图分析我的应用程序消耗的内存时,我看到" StringBuilder"和"字符串"正在采取相同数量的内存及其重复。 由于字符串的长度很长,因此占用较大的内存百分比。
有没有更好的方法来解决这个内存问题?
答案 0 :(得分:1)
要解决什么内存问题?您已经观察到行为,但没有解释这是一个什么样的问题。
请注意,在语句return result.ToString();
执行后,StringBuilder
引用的result
对象有资格进行垃圾回收(假设它是对象的唯一引用)。所以任何理论问题都应该是暂时的,可能的结果是很少或没有实际影响。
换句话说:假设您构建了100个长度为N的字符串。这些字符串的每个字符的标称开销为两个字节,因此内存中的成本为200 * N.在构建这些字符串的整个过程中,额外StringBuilder
对象的名义内存成本为N.是的,一次可能存在多个对象,但只有在无关紧要时。否则,.NET会垃圾收集旧版本以便为新版本腾出空间。
因此,对于额外的StringBuilder
,你的最终结果是1%的开销,比你的问题暗示的内存加倍要少得多。如果你只构建100个字符串就行了。有效开销与您实际创建的字符串数成反比,当然开销的重要性直接与相同数字成比例。换句话说,它越重要,实际影响就越小。
更一般地说,您认为您会找到什么样的选项? StringBuilder
类是处理可变字符串的最佳方式,即提供一种从部分创建字符串或以其他方式编辑字符串的方法(例如从中删除片段,重新排列它等)。也就是说,您可以实现自己的字符串编辑类,以专门的方式实现类似的效果。
但无论您使用什么来编辑字符串,如果您在完成时希望拥有System.String
的实例,那么您必须在字符串中包含两个数据副本:可编辑的版本,以及最终System.String
对象中的一个。您无法编辑System.String
对象(类型是不可变的),并且您无法将其他类型转换为System.String
的实例。
(尽管如此,我会注意到在较早的StringBuilder
实现中,StringBuilder
的缓冲区实际上只是作为引用复制到新System.String
{1}}对象。除非在调用ToString()
之后的某个时刻,StringBuilder
对象再次被修改,否则没有创建字符串数据的新副本。StringBuilder
的当前实现不会虽然这样做。它针对涉及更长字符串的方案进行了优化,避免了“缓冲区大小增加一倍”的重新分配成本,代价是始终需要最终ToString()
调用的数据副本。)
现在,如果您可以容忍使用字符串数据作为原始编辑对象(即StringBuilder
或其他一些自定义类)并且从不将数据转换为System.String
的实例,那么这显然是一种避免的方法第二份数据。在这种方法中,您永远不会打扰ToString()
电话。如初。
但是否则,你似乎要求不可能,因为没有机制可用于获取现有的字符缓冲区并强制System.String
使用该缓冲区作为其内部表示。即它是将任何其他数据结构(包括StringBuilder
)转换为System.String
实例的过程中固有的,即该数据的第二个副本。