题
什么是最有效的方式来串连串?
解决方案
的 StringBuilder.Append()
方法是更多使用操作员。但是我发现,在执行1000串联的或更小, String.Join()
甚至更有效率比 StringBuilder
.
StringBuilder sb = new StringBuilder();
sb.Append(someString);
唯一的问题 String.Join
是,你必须串连串用一个共同的界定符。(编辑)为@ryanversaw指出,可以使符串。空。
string key = String.Join("_", new String[]
{ "Customers_Contacts", customerID, database, SessionID });
其他提示
多黎各Mariani, 。净性的大师,不得不 一篇文章 在这个非常主题。它不是简单作为一个可能的嫌疑犯。基本建议是这样的:
如果你的图案看起来像:
x = f1(...) + f2(...) + f3(...) + f4(...)
这是一个concat并且它是比比,StringBuilder可能不会帮助。
如果你的图案看起来像:
if (...) x += f1(...)
if (...) x += f2(...)
if (...) x += f3(...)
if (...) x += f4(...)
然后你可能想StringBuilder.
但另一条款支持这个要求 来自埃里克利珀特在那里,他描述了优化执行一线 +
串联在一个详细的方式。
有6类型字符串串联:
- 使用加号(
+
)符号。 - 使用
string.Concat()
. - 使用
string.Join()
. - 使用
string.Format()
. - 使用
string.Append()
. - 使用
StringBuilder
.
在一个实验,已经证明 string.Concat()
是最好的方式方法,如果这句话是低于1000(大约)以及如果超过1000然后 StringBuilder
应该使用。
欲了解更多信息,请查看这个 网站.
string.Join()vs串。Concat()
String.Concat方法在这里等同于串。加入的方法援引一个空的分离器。追加一个空串的是快速的,但是不这样做甚至更快,所以 string.Concat 方法是将优这里。
规则的拇指
当连接三个动态串值或更低,使用传统的字符串连接。
当连接超过三个动态串的价值观,使用StringBuilder.
当建立一个大串几个字符串中,使用@字符串或内联+操作员。
大多数 时间StringBuilder是你最好的选择,但在有些情况下所示,员额,你至少应该考虑各种情况。
如果你在工作中的一环,StringBuilder是可能的路要走;这样可以节省你的开销创造新的弦。在代码,就只是运行一次,虽然串。Concat可能是罚款。
然而,波多黎各Mariani(.净化大师) 成立了一个测验 他在其陈述结束时,在大多数情况下,他建议串。格式。
这是最快的方法我已经发展了一个十年我的大规模自然语言的应用程序。我有变化 IEnumerable<T>
和其他类型的输入,并没有分离的不同类型(Char
, String
),但在这里,我告诉简单的情况 连接起来的所有串在一系列 进入一个字符串中,没有分离器。这里最新版本的开发和单元测试 C#7 和 .净4.7.
有两把钥匙到较高的绩效;第一是预先计算的精确总的尺寸要求。这一步骤是微不足道的当输入一个数组,如下所示。为处理 IEnumerable<T>
相反,它是值得的第一个收集串成一个临时阵列计算的总计(阵列需要避免叫 ToString()
超过一次每件,因为从技术上讲,鉴于可能的副作用,这样做可能改变预期的语义上的'string加入'操作)。
接着,鉴于共分配大小最终串,最大提高的性能是获得了通过 建筑结果串在的地方.这样要求(也许有争议的)技术的暂停不变性的一个新的 String
这是最初分配充分的零。任何此类争议,一边,但是...
...注意,这是唯一大串联方案在这一页面这完全可以避免 额外的轮的分配和复制 由的
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);
我应该提及,这种代码已经略微修改,从我使用我自己。在原来的我 呼叫的 cpblk IL指令 从 C# 要做到实际的复制。为简单起见和便携在这里的代码,我更换,与P/调用 memcpy
相反,正如你可以看到。对于最高性能64(但也许不x86),您可能想要使用 cpblk 方法来代替。
从这个 MSDN文章:
有一些相关的开销 创建一个StringBuilder目的,两个 在时间和存储器中。在一台机器 快速存储器、StringBuilder变 值得如果你做大约五 操作。作为一项规则的拇指,我 会说,10个或更多的串行动 是有理由的开销 任何机器,甚至更慢的一个。
所以,如果你信任MSDN去StringBuilder如果你必须做更多的10字符串中业务/连接-否则,简单的文字concat与'+'是好的。
增加其他的答案,请记住, StringBuilder可以告诉一个初始存储量的分配.
的 能力 参数规定的最大数字,可以被存储器中存储的分配由目前的实例。它的价值是分配到的 能力 财产。如果数字来存在的现实超过了这个 能力 值,StringBuilder目分配额外存储器中存储。
如果 能力 是零,实施特定的默认能力是使用。
多次追加StringBuilder,没有预先分配的可能结果在很多不必要的拨款只是喜欢多次合并定期串。
如果你知道多久,最终串将是,可以平凡计算,或者可以做出的猜测,有关的常见情况(分配过多并不一定是坏事),则应提供该信息的构造或 能力 财产。 尤其是 时运行性能测试的比较StringBuilder用其他方法,如串。Concat,其做同样的事情。任何测试你在网上看到其中不包括StringBuilder预先分配在其比较是错误的。
如果你不能让任何种类的猜测有关的大小,你可能编写实用功能,其应当有它自己的任择参数用于控制预先分配。
同样重要的是要指出来,你应该使用 +
操作者如果你是连接 字符串.
当你串连串的文字或串常通过使用运营商,编译器创建一个单一串。没有运行时间串联的发生。
下面可能是一个更多的替代解决方案连接的多个串。
String str1 = "sometext";
string str2 = "some other text";
string afterConcate = $"{str1}{str2}";
效率最高的是利用StringBuilder,像这样:
StringBuilder sb = new StringBuilder();
sb.Append("string1");
sb.Append("string2");
...etc...
String strResult = sb.ToString();
@jonezy:String.Concat是好的,如果你有几个小东西。但如果你连接兆字节的数据,你的节目可能会罐。
试试这2件的代码,你会找到解决方案。
static void Main(string[] args)
{
StringBuilder s = new StringBuilder();
for (int i = 0; i < 10000000; i++)
{
s.Append( i.ToString());
}
Console.Write("End");
Console.Read();
}
Vs
static void Main(string[] args)
{
string s = "";
for (int i = 0; i < 10000000; i++)
{
s += i.ToString();
}
Console.Write("End");
Console.Read();
}
你会发现,1号码最终会真的快速存储器将是一个良好的数额。
第二代码也许存储器将是确定的,但它将需要更长的时间...更长的时间。所以如果你有一个应用程序,为一个很大的用户和你需要的速度,使用1日。如果你有一个应用程序,用于短期的一个用户应用程序,也许你可以同时使用或第2将更多的"自然"的开发。
欢呼声。
系统。串是一成不变的。当我们修改的价值的一串变然后,一个新的存储器被分配给新的价值和先前存分配释放。系统。StringBuilder的设计概念的一个可变的字符串中的各种操作可以执行而不分配单独的存储位置用于修改弦。
另一种解决方案:
内部循环,使用名单,而不是串。
List<string> lst= new List<string>();
for(int i=0; i<100000; i++){
...........
lst.Add(...);
}
return String.Join("", lst.ToArray());;
它是非常非常快。
这真的取决于您的使用模式。一个详细的基准之间的串。加入,string,Concat和串。格式可以在这里找到: String.格式不适用于密集的记录
(这实际上是相同的答案给我 此 问题)
对于只有两个串,你肯定不想使用StringBuilder.有一些阈值之上的StringBuilder开销不到开销的分配多串。
因此,对于更多的2-3个字符串中使用 DannySmurf的代码.否则,只是使用操作员。
它将取决于代码。StringBuilder是更有效率一般,但是如果你只是在连接几个字符串这样做的所有一线、代码优化可能将照顾你。重要的是要考虑怎样的代码看起来太:对于较大的集StringBuilder将使其更易于阅读,对于小的StringBuilder只会增加不必要的混乱。