连接字符串最有效的方法是什么?
当前回答
系统。字符串是不可变的。当我们修改一个字符串变量的值时,一个新的内存被分配给新的值,之前的内存分配被释放。系统。StringBuilder被设计为具有可变字符串的概念,其中可以执行各种操作,而无需为修改后的字符串分配单独的内存位置。
其他回答
下面可能是连接多个字符串的另一种解决方案。
String str1 = "sometext";
string str2 = "some other text";
string afterConcate = $"{str1}{str2}";
字符串插值
这是我为我的大规模NLP应用程序进化了十多年来最快的方法。我有IEnumerable<T>和其他输入类型的变化,有和没有不同类型的分隔符(Char, String),但在这里我展示了将数组中的所有字符串连接到单个字符串的简单情况,没有分隔符。这里的最新版本是在c# 7和。net 4.7上开发和单元测试的。
提高性能有两个关键;第一种方法是预先计算所需的确切总大小。当输入是如下所示的数组时,这一步是微不足道的。为了处理IEnumerable<T>,值得首先将字符串收集到一个临时数组中以计算总数(该数组需要避免每个元素多次调用ToString(),因为从技术上讲,考虑到副作用的可能性,这样做可能会改变'字符串连接'操作的预期语义)。
接下来,给定最终字符串的总分配大小,通过就地构建结果字符串可以获得最大的性能提升。要做到这一点,需要使用(可能有争议的)技术暂时暂停新String的不可变性,该String最初被分配为全0。然而,抛开这些争议不谈……
...请注意,这是本页上唯一的大容量连接解决方案,它完全避免了String构造函数额外的分配和复制。
完整的代码:
/// <summary>
/// Concatenate the strings in 'rg', none of which may be null, into a single String.
/// </summary>
public static unsafe String StringJoin(this String[] rg)
{
int i;
if (rg == null || (i = rg.Length) == 0)
return String.Empty;
if (i == 1)
return rg[0];
String s, t;
int cch = 0;
do
cch += rg[--i].Length;
while (i > 0);
if (cch == 0)
return String.Empty;
i = rg.Length;
fixed (Char* _p = (s = new String(default(Char), cch)))
{
Char* pDst = _p + cch;
do
if ((t = rg[--i]).Length > 0)
fixed (Char* pSrc = t)
memcpy(pDst -= t.Length, pSrc, (UIntPtr)(t.Length << 1));
while (pDst > _p);
}
return s;
}
[DllImport("MSVCR120_CLR0400", CallingConvention = CallingConvention.Cdecl)]
static extern unsafe void* memcpy(void* dest, void* src, UIntPtr cb);
我应该提到,这段代码与我自己使用的代码相比略有修改。在原文中,我从c#调用cpblk IL指令来执行实际的复制。为了代码的简单性和可移植性,我将其替换为P/Invoke memcpy,如您所见。为了在x64(但可能不是x86)上获得最高性能,您可能想要使用cpblk方法。
最有效的方法是使用StringBuilder,如下所示:
StringBuilder sb = new StringBuilder();
sb.Append("string1");
sb.Append("string2");
...etc...
String strResult = sb.ToString();
@jonezy:字符串。Concat是好的,如果你有一些小东西。但是,如果您正在连接兆字节的数据,那么您的程序可能会崩溃。
StringBuilder并不总是更快:
经验法则
当连接三个或更少的动态字符串值时,使用传统的字符串连接。 当连接三个以上的动态字符串值时,请使用StringBuilder。 当从多个字符串字面值构建一个大字符串时,可以使用@字符串字面值或内联+操作符。
大多数情况下,StringBuilder是您最好的选择,但在某些情况下,如那篇文章所示,您至少应该考虑每种情况。
这取决于你的使用模式。 字符串之间的详细基准测试。连接,字符串,Concat和字符串。格式可以在这里找到:字符串。格式不适合密集的日志记录
(这实际上是我对这个问题的回答)
推荐文章
- 实体框架核心:在上一个操作完成之前,在此上下文中开始的第二个操作
- 如何为构造函数定制Visual Studio的私有字段生成快捷方式?
- 为什么Visual Studio 2015/2017/2019测试运行器没有发现我的xUnit v2测试
- 确定记录是否存在的最快方法
- 如何使用JSON确保字符串是有效的JSON。网
- Printf与std::字符串?
- AppSettings从.config文件中获取值
- 通过HttpClient向REST API发布一个空体
- 阅读GHC核心
- 如何检查IEnumerable是否为空或空?
- 不区分大小写的“in”
- 自动化invokerrequired代码模式
- 我如何得到一个字符串的前n个字符而不检查大小或出界?
- 没有ListBox。SelectionMode="None",是否有其他方法禁用列表框中的选择?
- 在c#代码中设置WPF文本框的背景颜色