在C#面对字符串拼接的需求时,写法同样简洁的string.Join方法和Enumerable.Aggregate中或许是一个值得思考的问题。
Linq与多线程的效率优势在现时的版本中15倍的速度优势是极其明显的,而在面对C#语法糖的基础功能时,效率却似乎显得捉襟见肘。
测试实验
1. 配置测试计时方法
public static void TestAction(Action action, int times = 100)
{
Stack<double> values = new Stack<double>();
for (int i = 0; i < times; i++)
{
Run();
action.Invoke();
values.Push(Stop().TotalMilliseconds);
}
Console.WriteLine("Max:" + values.Max());
Console.WriteLine("Max5A:" + values.OrderByDescending(x => x).Take(5).Average());
Console.WriteLine("Max10:" + values.OrderByDescending(x => x).Skip(5).Take(5).Average());
Console.WriteLine("Min:" + values.Min());
Console.WriteLine("Min5A:" + values.OrderBy(x => x).Take(5).Average());
Console.WriteLine("Min10:" + values.OrderBy(x => x).Skip(5).Take(5).Average());
Console.WriteLine("Avg:" + values.Average());
}
2. 测试
2.1 第一组测试
输出首先生成包含1000个字符串的数组,设置增长字符,设置测试次数为1000,然后启动测试
var list = Enumerable.Range(0, 1000).Select(x => x.ToString()).ToArray();
StopWatch.TestAction(() =>
{
string.Join("U+002C", list);
}, 1000);
StopWatch.TestAction(() =>
{
list.Aggregate((a, b) => a + "U+002C" + b);
}, 1000);
输出结果
单次实验结论
string.Join的平均效率为Enumerable.Aggregate的64倍。
2.2 第二组测试
输出首先生成包含1000个字符串的数组,设置增长字符,设置测试次数为10000,然后启动测试
var list = Enumerable.Range(0, 1000).Select(x => x.ToString()).ToArray();
StopWatch.TestAction(() =>
{
string.Join("U+002C", list);
}, 10000);
StopWatch.TestAction(() =>
{
list.Aggregate((a, b) => a + "U+002C" + b);
}, 10000);
输出结果
单次实验结论
string.Join的平均效率为Enumerable.Aggregate的60倍。
结论
众所周知,随着实验的循环次数,平均效率的差值将连贯缩减。而在大部分应用场景中,数千及数万次的已经极为少见。
在较少次数的调用中,string.Join的平均效率是显著优于Enumerable.Aggregate的。