Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 字符串和StringBuilder消耗的内存重复_C#_.net_String_Performance_Memory Leaks - Fatal编程技术网

C# 字符串和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进行如下操作

        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,并且可能避免为临时对象分配内存。解决此内存问题吗?这是个问题吗?或者你只是有这么多的空闲内存,垃圾收集器没有运行?谢谢你这么好的解释。我希望我需要将数据类型从字符串更改为字节或其他数据类型。因为字符串只是用于从一个系统到另一个系统的通信。