使用前缀,后缀和分隔符连接字符串的最快方法

Jod*_*ell 13 .net c# string

UPDATE

按照奶酪先生的回答,似乎是

public static string Join<T>(string separator, IEnumerable<T> values)
Run Code Online (Sandbox Code Playgroud)

超载string.Join从使用StringBuilderCache类中获得优势.

有没有人对本声明的正确性或原因有任何反馈意见?

我可以写自己的,

public static string Join<T>(
    string separator,
    string prefix,
    string suffix,
    IEnumerable<T> values)
Run Code Online (Sandbox Code Playgroud)

使用StringBuilderCache该类的函数?


在提交了我对这个问题的答案后,我得到了一些分析,其中哪个是最佳表现的答案.

我在控制台Program类中编写了这段代码来测试我的想法.

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;

class Program
{
    static void Main()
    {
        const string delimiter = ",";
        const string prefix = "[";
        const string suffix = "]";
        const int iterations = 1000000;

        var sequence = Enumerable.Range(1, 10).ToList();

        Func<IEnumerable<int>, string, string, string, string>[] joiners =
            {
                Build,
                JoinFormat,
                JoinConcat
            };

        // Warmup
        foreach (var j in joiners)
        {
            Measure(j, sequence, delimiter, prefix, suffix, 5);
        }

        // Check
        foreach (var j in joiners)
        {
            Console.WriteLine(
                "{0} output:\"{1}\"",
                j.Method.Name,
                j(sequence, delimiter, prefix, suffix));
        }

        foreach (var result in joiners.Select(j => new
                {
                    j.Method.Name,
                    Ms = Measure(
                        j,
                        sequence,
                        delimiter,
                        prefix,
                        suffix,
                        iterations)
                }))
        {
            Console.WriteLine("{0} time = {1}ms", result.Name, result.Ms);
        }

        Console.ReadKey();
    }

    private static long Measure<T>(
        Func<IEnumerable<T>, string, string, string, string> func,
        ICollection<T> source,
        string delimiter,
        string prefix,
        string suffix,
        int iterations)
    {
        var stopwatch = new Stopwatch();

        stopwatch.Start();
        for (var i = 0; i < iterations; i++)
        {
            func(source, delimiter, prefix, suffix);
        }

        stopwatch.Stop();

        return stopwatch.ElapsedMilliseconds;
    }

    private static string JoinFormat<T>(
        IEnumerable<T> source,
        string delimiter,
        string prefix,
        string suffix)
    {
        return string.Format(
            "{0}{1}{2}",
            prefix,
            string.Join(delimiter, source),
            suffix);
    }

    private static string JoinConcat<T>(
        IEnumerable<T> source,
        string delimiter,
        string prefix,
        string suffix)
    {
        return string.Concat(
            prefix,
            string.Join(delimiter, source),
            suffix);
    }

    private static string Build<T>(
        IEnumerable<T> source,
        string delimiter,
        string prefix,
        string suffix)
    {
        var builder = new StringBuilder();
        builder = builder.Append(prefix);

        using (var e = source.GetEnumerator())
        {
            if (e.MoveNext())
            {
                builder.Append(e.Current);
            }

            while (e.MoveNext())
            {
                builder.Append(delimiter);
                builder.Append(e.Current);
            }
        }

        builder.Append(suffix);
        return builder.ToString();
    }
}
Run Code Online (Sandbox Code Playgroud)

运行代码,在发布配置中,使用优化构建,从命令行我得到这样的输出.

...

建造时间= 1555ms

JoinFormat时间= 1715ms

JoinConcat时间= 1452ms

这里唯一的惊喜(对我来说)是Join-Format组合是最慢的.考虑后这个答案,这使得多一点意义上说,输出string.Join是由外加工StringBuilderstring.Format,有采用这种方法固有的延迟.

沉思之后,我不清楚怎么string.Join能更快.我已经读过它的用法,FastAllocateString()但是我不明白如何在不调用.ToString()每个成员的情况下准确预先分配缓冲区sequence.为什么Join-Concat组合更快?

一旦我的理解是,这将有可能写我自己的unsafe string Join功能,这需要额外的prefixsuffix参数,并进行了"安全"的替代品.

我有过几次尝试,虽然他们工作,但他们并不快.

Rui*_*mba -1

尝试在方法中使用StringBuilder.AppendFormatBuild<T>而不是StringBuilder.Append

  • 地点和原因?我不知道这有什么帮助。 (3认同)