C# 字符串和StringBuilder消耗的内存重复
我需要几根弦。我正在使用StringBuilder进行如下操作C# 字符串和StringBuilder消耗的内存重复,c#,.net,string,performance,memory-leaks,C#,.net,String,Performance,Memory Leaks,我需要几根弦。我正在使用StringBuilder进行如下操作 StringBuilder result = new StringBuilder(length); 长度是我想要在末尾的字符串的“长度” “长度”的数字较大。 要得到字符串,我需要做 return result.ToString(); 当我试图分析我的应用程序所消耗的内存时,我看到“StringBuilder”和“String”占用了相同数量的内存及其副本。 由于字符串的长度较长,因此它占用了较大
StringBuilder result = new StringBuilder(length);
长度是我想要在末尾的字符串的“长度”
“长度”的数字较大。
要得到字符串,我需要做
return result.ToString();
当我试图分析我的应用程序所消耗的内存时,我看到“StringBuilder”和“String”占用了相同数量的内存及其副本。
由于字符串的长度较长,因此它占用了较大的内存%
有没有更好的方法来解决这个内存问题 解决什么内存问题?你观察到了一种行为,但没有解释它是一个什么样的问题
注意,在语句之后立即返回result.ToString()代码>执行时,result
引用的StringBuilder
对象符合垃圾收集的条件(假设这是对该对象的唯一引用)。因此,任何理论问题都应该是暂时的,可能的结果几乎没有实际影响
换句话说:假设您构建了100个长度为N的字符串。这些字符串的标称开销为每个字符两个字节,因此内存开销为200*N。在构建这些字符串的整个过程中,额外的StringBuilder
对象的标称内存开销为N。是,一次可能存在不止一个这样的物体,但只有当它不重要的时候。否则,.NET将垃圾收集旧的,为新的腾出空间
因此,对于额外的StringBuilder
,您的最终结果是1%的开销,比您的问题所暗示的内存加倍要少得多。如果你只构建100个字符串。有效开销与实际创建的字符串数成反比,当然,开销的重要性与该数字成正比。换句话说,它越重要,实际影响就越小
一般来说,你认为你会找到什么样的选择?StringBuilder
类是处理可变字符串的最佳方法,即提供一种从部分创建字符串或以其他方式编辑字符串的方法(例如从中删除片段、重新排列字符串等)。也就是说,您可以实现自己的字符串编辑类,以专门的方式实现类似的效果
但是,不管您使用什么来编辑字符串,如果您在编辑完后希望有一个System.string
的实例,那么字符串中必然会有两个数据副本:一个在可编辑版本中,另一个在最终的System.string
对象中。您不能编辑System.String
对象(类型是不可变的),也不能神奇地将其他类型转换为System.String
的实例
(尽管作为旁白,我将注意到在StringBuilder
的旧实现中,StringBuilder
的缓冲区实际上只是作为对新System.String
对象的引用而复制的。除非在调用ToString()之后的某个时刻,否则不会创建字符串数据的新副本。)
,再次修改了StringBuilder
对象。但是StringBuilder
的当前实现并没有这样做。它针对涉及更长字符串的场景进行了优化,避免了“缓冲区大小加倍”的重新分配成本,而最终的ToString()总是需要数据副本
call)
现在,如果您可以容忍使用字符串数据作为原始编辑对象(即StringBuilder
或其他一些自定义类),并且从不将数据转换为System.string
的实例,那么这显然是避免数据的第二个副本的一种方法。在这种方法中,您永远不会为ToString()
调用而烦恼。永远
但除此之外,您似乎在寻求不可能的结果,因为没有任何机制可用于获取现有的字符缓冲区并强制System.String
使用该缓冲区作为其内部表示。也就是说,在将任何其他数据结构(包括StringBuilder
)转换为System.String
实例的过程中,都会生成该数据的第二个副本。在不知道您试图解决的问题的情况下,很难回答该问题。但是如果您的应用程序因为大字符串而使用了太多内存,那么看起来您根本不应该使用字符串。流式方法可能会更好。是的,我们需要序列化它,并且需要从另一方读取。所以我们使用的是字符串。如果你想使用字符串,那么你必须承受后果。但是,如果使用StringBuilder连接已知数量的字符串(在编译时),则最好使用+-运算符,因为编译器会将其转换为String.Concat,并且可能避免为临时对象分配内存。解决此内存问题吗?这是个问题吗?或者你只是有这么多的空闲内存,垃圾收集器没有运行?谢谢你这么好的解释。我希望我需要将数据类型从字符串更改为字节或其他数据类型。因为字符串只是用于从一个系统到另一个系统的通信。