连接字符串最有效的方法是什么?
当前回答
系统。字符串是不可变的。当我们修改一个字符串变量的值时,一个新的内存被分配给新的值,之前的内存分配被释放。系统。StringBuilder被设计为具有可变字符串的概念,其中可以执行各种操作,而无需为修改后的字符串分配单独的内存位置。
其他回答
除了其他答案之外,请记住StringBuilder可以被告知要分配的初始内存量。
容量参数定义了当前实例分配的内存中可以存储的最大字符数。它的值被赋给Capacity属性。如果当前实例中存储的字符数量超过了这个容量值,StringBuilder对象就会分配额外的内存来存储这些字符。 如果容量为零,则使用特定于实现的默认容量。
重复添加到未预先分配的StringBuilder可能会导致大量不必要的分配,就像重复连接常规字符串一样。
If you know how long the final string will be, can trivially calculate it, or can make an educated guess about the common case (allocating too much isn't necessarily a bad thing), you should be providing this information to the constructor or the Capacity property. Especially when running performance tests to compare StringBuilder with other methods like String.Concat, which do the same thing internally. Any test you see online which doesn't include StringBuilder pre-allocation in its comparisons is wrong.
如果你无法猜测它的大小,你可能在写一个效用函数它应该有自己的可选参数来控制预分配。
系统。字符串是不可变的。当我们修改一个字符串变量的值时,一个新的内存被分配给新的值,之前的内存分配被释放。系统。StringBuilder被设计为具有可变字符串的概念,其中可以执行各种操作,而无需为修改后的字符串分配单独的内存位置。
最有效的方法是使用StringBuilder,如下所示:
StringBuilder sb = new StringBuilder();
sb.Append("string1");
sb.Append("string2");
...etc...
String strResult = sb.ToString();
@jonezy:字符串。Concat是好的,如果你有一些小东西。但是,如果您正在连接兆字节的数据,那么您的程序可能会崩溃。
这取决于代码。 StringBuilder通常更高效,但如果您只是连接几个字符串并在一行中完成所有操作,那么代码优化可能会为您解决这个问题。考虑代码的外观也很重要:对于较大的集合,StringBuilder将使其更容易阅读,对于较小的集合,StringBuilder只会增加不必要的混乱。
我已经测试了本页中的所有方法,最后我开发出了最快且内存成本更低的解决方案。
注:在Framework 4.8中测试
[MemoryDiagnoser]
public class StringConcatSimple
{
private string
title = "Mr.", firstName = "David", middleName = "Patrick", lastName = "Callan";
[Benchmark]
public string FastConcat()
{
return FastConcat(
title, " ",
firstName, " ",
middleName, " ",
lastName);
}
[Benchmark]
public string StringBuilder()
{
var stringBuilder =
new StringBuilder();
return stringBuilder
.Append(title).Append(' ')
.Append(firstName).Append(' ')
.Append(middleName).Append(' ')
.Append(lastName).ToString();
}
[Benchmark]
public string StringBuilderExact24()
{
var stringBuilder =
new StringBuilder(24);
return stringBuilder
.Append(title).Append(' ')
.Append(firstName).Append(' ')
.Append(middleName).Append(' ')
.Append(lastName).ToString();
}
[Benchmark]
public string StringBuilderEstimate100()
{
var stringBuilder =
new StringBuilder(100);
return stringBuilder
.Append(title).Append(' ')
.Append(firstName).Append(' ')
.Append(middleName).Append(' ')
.Append(lastName).ToString();
}
[Benchmark]
public string StringPlus()
{
return title + ' ' + firstName + ' ' +
middleName + ' ' + lastName;
}
[Benchmark]
public string StringFormat()
{
return string.Format("{0} {1} {2} {3}",
title, firstName, middleName, lastName);
}
[Benchmark]
public string StringInterpolation()
{
return
$"{title} {firstName} {middleName} {lastName}";
}
[Benchmark]
public string StringJoin()
{
return string.Join(" ", title, firstName,
middleName, lastName);
}
[Benchmark]
public string StringConcat()
{
return string.
Concat(new String[]
{ title, " ", firstName, " ",
middleName, " ", lastName });
}
}
是的,它使用不安全
public static unsafe string FastConcat(string str1, string str2, string str3, string str4, string str5, string str6, string str7)
{
var capacity = 0;
var str1Length = 0;
var str2Length = 0;
var str3Length = 0;
var str4Length = 0;
var str5Length = 0;
var str6Length = 0;
var str7Length = 0;
if (str1 != null)
{
str1Length = str1.Length;
capacity = str1Length;
}
if (str2 != null)
{
str2Length = str2.Length;
capacity += str2Length;
}
if (str3 != null)
{
str3Length = str3.Length;
capacity += str3Length;
}
if (str4 != null)
{
str4Length = str4.Length;
capacity += str4Length;
}
if (str5 != null)
{
str5Length = str5.Length;
capacity += str5Length;
}
if (str6 != null)
{
str6Length = str6.Length;
capacity += str6Length;
}
if (str7 != null)
{
str7Length = str7.Length;
capacity += str7Length;
}
string result = new string(' ', capacity);
fixed (char* dest = result)
{
var x = dest;
if (str1Length > 0)
{
fixed (char* src = str1)
{
Unsafe.CopyBlock(x, src, (uint)str1Length * 2);
x += str1Length;
}
}
if (str2Length > 0)
{
fixed (char* src = str2)
{
Unsafe.CopyBlock(x, src, (uint)str2Length * 2);
x += str2Length;
}
}
if (str3Length > 0)
{
fixed (char* src = str3)
{
Unsafe.CopyBlock(x, src, (uint)str3Length * 2);
x += str3Length;
}
}
if (str4Length > 0)
{
fixed (char* src = str4)
{
Unsafe.CopyBlock(x, src, (uint)str4Length * 2);
x += str4Length;
}
}
if (str5Length > 0)
{
fixed (char* src = str5)
{
Unsafe.CopyBlock(x, src, (uint)str5Length * 2);
x += str5Length;
}
}
if (str6Length > 0)
{
fixed (char* src = str6)
{
Unsafe.CopyBlock(x, src, (uint)str6Length * 2);
x += str6Length;
}
}
if (str7Length > 0)
{
fixed (char* src = str7)
{
Unsafe.CopyBlock(x, src, (uint)str7Length * 2);
}
}
}
return result;
}
您可以编辑该方法并使其适应您的情况。例如,你可以让它像这样
FastConcat(string str1, string str2, string str3 = null, string str4 = null, string str5 = null, string str6 = null, string str7 = null)
推荐文章
- 实体框架核心:在上一个操作完成之前,在此上下文中开始的第二个操作
- 如何为构造函数定制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文本框的背景颜色