连接字符串最有效的方法是什么?


当前回答

最有效的方法是使用StringBuilder,如下所示:

StringBuilder sb = new StringBuilder();
sb.Append("string1");
sb.Append("string2");
...etc...
String strResult = sb.ToString();

@jonezy:字符串。Concat是好的,如果你有一些小东西。但是,如果您正在连接兆字节的数据,那么您的程序可能会崩溃。

其他回答

如果你在循环中操作,StringBuilder可能是最好的选择;它节省了定期创建新字符串的开销。在只运行一次的代码中,字符串。Concat可能没问题。

然而,Rico Mariani(。NET优化大师)做了一个测试,他在测试的最后说,在大多数情况下,他建议使用String.Format。

对于只有两个字符串,您肯定不希望使用StringBuilder。如果超过某个阈值,StringBuilder开销将小于分配多个字符串的开销。

所以,对于超过2-3个字符串,使用DannySmurf的代码。否则,只需使用+运算符。

最有效的方法是使用StringBuilder,如下所示:

StringBuilder sb = new StringBuilder();
sb.Append("string1");
sb.Append("string2");
...etc...
String strResult = sb.ToString();

@jonezy:字符串。Concat是好的,如果你有一些小东西。但是,如果您正在连接兆字节的数据,那么您的程序可能会崩溃。

我已经测试了本页中的所有方法,最后我开发出了最快且内存成本更低的解决方案。

注:在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)

系统。字符串是不可变的。当我们修改一个字符串变量的值时,一个新的内存被分配给新的值,之前的内存分配被释放。系统。StringBuilder被设计为具有可变字符串的概念,其中可以执行各种操作,而无需为修改后的字符串分配单独的内存位置。