C#中字符串拼接不安全,需要用StringBuilder吗?我的问题是:C#中的字符串连接是否安全?如果字符串连接导致意外错误,并且用StringBuilder替换该字符串连接导致这些错误消失,这可能表明什么?背景:我正在开发一个小型命令行C#应用程序。它采用命令行参数,执行稍微复杂的SQL查询,并将大约1300行数据输出到一个格式化的XML文件。我的初始程序在调试模式下始终运行良好。但是,在发布模式下,它会获得大约第750个SQL结果,然后因错误而死亡。错误是无法读取某列数据,即使SqlDataReader对象的Read()方法刚刚返回true。通过对代码中的所有操作使用StringBuilder来解决此问题,“string1+string2”之前已经存在。我不是在谈论SQL查询循环中的字符串连接,其中StringBuilder已在使用中。我说的是代码前面两个或三个短字符串变量之间的简单连接。我的印象是C#足够聪明,可以通过添加一些字符串来处理内存管理。我错了吗?或者这是否表明其他一些代码问题?除了您正在做的事情之外,最好使用XMLAPI而不是String或StringBuilder我怀疑您看到的错误是由于字符串连接造成的。也许切换到StringBuilder只是掩盖错误或优雅地传递它,但我怀疑使用字符串真的是原因。回答您的问题:C#(和一般的.NET)中的字符串连接是“安全的”,但是如您所描述的那样在紧密循环中进行连接会导致严重的内存压力并损坏垃圾收集器导致压力。我猜你所说的错误与某种资源耗尽有关,但如果你能提供更多细节会很有帮助——例如,你有没有遇到异常?应用程序是否异常终止?背景:.NET字符串是不可变的,所以当您进行这样的连接时:varstringList=newList{"aaa","bbb","ccc","ddd",//...};字符串结果=String.Empty;foreach(varsinstringList){结果=结果+s;这大致等同于以下内容:stringresult="";结果=“aaa”字符串temp1=结果+“bbb”;结果=临时1;字符串temp2=temp1+"ccc";结果=温度2;字符串temp3=temp2+"ddd";结果=温度3;//...结果=tempN+x;这个例子的目的是强调每次循环都会导致分配一个新的临时字符串。由于字符串是不可变的,因此在运行时没有其他选择,但每次将另一个字符串添加到结果末尾时都会分配一个新字符串。当结果字符串不断更新以指向最新和最好的中间结果时,您会生成大量这些未命名的临时字符串,这些字符串几乎可以立即被垃圾回收。在此连接结束时,您将在内存中存储以下字符串(为简单起见,假设垃圾收集器尚未运行)。字符串a="aaa";字符串b="bbb";字符串c="ccc";//...字符串temp1="aaabbb";字符串temp2="aaabbbccc";字符串temp3="aaabbbcccddd";stringtemp4="aaabbbcccdddeee";字符串temp5="aaabbbcccdddeeefff";stringtemp6="aaabbbcccdddeeefffggg";//...虽然所有这些隐式临时变量几乎可以立即被垃圾回收,但它们仍然需要分配。当在一个紧密的循环中执行连接时,这会给垃圾收集器带来很大的压力,而且如果不出意外的话,会使您的代码运行非常缓慢。我亲眼目睹了这对性能的影响,并且随着连接字符串变大,它变得非常明显。如果您要进行多个字符串连接,推荐的方法是始终使用StringBuilder。StringBuilder使用可变缓冲区来减少构建字符串所需的分配次数。如果您在循环中连接大量字符串,则字符串连接比使用StringBuilder占用更多内存。在极端情况下,您可能会耗尽内存。这几乎可以肯定是代码中的错误。也许您要连接很多字符串。或者也许完全是别的东西。我会在没有任何先入为主的原因的情况下返回调试-如果您仍然遇到问题,请尝试将其减少到重现问题和发布代码所需的最低限度。连接版本与字符串生成器版本需要多长时间?您与数据库的连接可能已关闭。如果您要进行大量联接,我会使用StringBuilder,因为它更高效。一个原因可能是字符串在.Net中是不可变的,因此当您执行诸如连接之类的操作时,实际上是在创建一个新字符串。另一个可能的原因是字符串长度是一个int,所以最大可能的长度是Int32.MaxValue或2,147,483,647。在任何一种情况下,StringBuilder都优于“string1+string2”这种类型的操作。虽然,最好使用内置的XML功能。这是我在黑暗中拍摄的照片…….NET中的字符串(不是stringbuilders)进入字符串实习生池。这基本上是一个由CLR管理的区域,用于共享字符串以提高性能。这里肯定有一些限制,虽然我不知道那个限制是什么。我认为您所做的所有连接都达到了弦乐练习池的上限。所以SQL说是的,我有一个值,但它不能把它放在任何地方,所以你得到一个异常。一个快速简单的测试是nGen你的组件,看看你是否仍然得到错误。在nGen'ing之后,您的应用程序将不再使用该池。如果做不到这一点,我会联系Microsoft尝试获取一些详细信息。我认为我的想法听起来很有道理,但我不知道为什么它在调试模式下有效。也许在调试模式下,字符串没有具体化。我也不是专家。string.Concat(string[])是迄今为止连接字符串最快的方法。当在循环中使用时,它很容易在性能方面破坏StringBuilder,尤其是在每次迭代都创建StringBuilder的情况下。如果你谷歌“c#stringformatvsstringbuilder”或类似的,将会有大量的参考。http://www.codeproject.com/KB/cs/StringBuilder_vs_String.aspx让您了解时代。这里string.Join赢得了连接测试,但我相信这是因为使用了string.Concat(string,string)而不是采用数组的重载版本。如果您查看由不同方法生成的MSIL代码,您可以了解幕后发生的事情。将字符串组合在一起时,我总是使用StringBuilder。它就是为此而设计的,只使用“string1+string2”会更有效率。以上是C#学习教程:StringconcatenationisnotsafeinC#,doIneedtouseStringBuilder?如果所有分享的内容对你有用,需要进一步了解C#学习教程,希望大家多多关注。本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处:
