String.Concat(String, String, String, String)有什么用?

5
如果您需要将5个或更多字符串连接起来,可以使用String.Concat(),此时它会使用Concat(String[])。为什么不总是使用Concat(String[]),而摆脱Concat(String, String)Concat(String, String, String)Concat(String, String, String, String)的需要呢?那么微软为什么不只在想要连接一个或多个字符串时使用Concat(String[])呢?

1
(在C#1/.NET1.0中)params是什么? - user2864740
1
@user2864740 我也是这么想的,刚刚查了一下MSDN,它说string.concat重载参数已经包含在1.0版本中了。 - Robert Levy
@RobertLevy 更加离题了:params 可以作为向后兼容的更改应用吗(例如在前向 API 中反映)?你能找到原始的 1.0 文档吗? - user2864740
我的观点是这里的性能提升微不足道。你可以自己尝试并测试它。大多数情况下,这只是为了方便 - 类似于语法糖。 - Andrew Savinykh
2个回答

7
根据参考来源Concat(String[])的实现方式,如下所示:
public static string Concat(params string[] values)
{       
    int totalLength = 0; // variable to calculate total length
    string[] strArray = new string[values.Length]; // second array
    for (int i = 0; i < values.Length; i++) // first loop
    {
        string str = values[i];            
        totalLength += strArray[i].Length;           
    }

    return ConcatArray(strArray, totalLength);
}

private static string ConcatArray(string[] values, int totalLength)
{
    string dest = FastAllocateString(totalLength);
    int destPos = 0; // variable to calculate current position
    for (int i = 0; i < values.Length; i++) // second loop
    {
        FillStringChecked(dest, destPos, values[i]);
        destPos += values[i].Length;
    }
    return dest;
}

Concat(String, String, String)等方法更加优化。它们避免了为参数创建字符串数组,避免了循环(每个循环都有变量、递增和检查逻辑),它们不使用变量计算总字符串长度和生成字符串中当前位置:

public static string Concat(string str0, string str1, string str2)
{
    int length = (str0.Length + str1.Length) + str2.Length;
    string dest = FastAllocateString(length);
    FillStringChecked(dest, 0, str0);
    FillStringChecked(dest, str0.Length, str1);
    FillStringChecked(dest, str0.Length + str1.Length, str2);
    return dest;
}

注意:我跳过了参数验证代码(空值被替换为空字符串),只显示区别。


那么为什么微软决定在Concat(String, String, String, String)停止,而不是创建Concat(String, String, String, String, String)?你在哪里划线呢? - David Klempfner
1
他们避免为参数创建字符串数组......等等,什么?不是方法创建字符串数组,而是它的调用者! - Andrew Savinykh
@zespri的Concat(params string[] values)是使用了 params 关键字。 - Sergey Berezovskiy
1
对于这样的东西,你必须有某种形式的截断。4似乎是合乎逻辑的,因为你可以将它们串联起来:string.Concat("1", "2", "3", string.Concat("4", "5", "6", "7"))…… 同样的用例也适用于 Tuple<T1, T2, T3.. 等等,其中 T8 是另一个 Tuple,如果你需要更大的话。 - Simon Whitehead
4
我猜他们尽可能地查看了许多生产代码,并决定提供覆盖最多代码的4个选项(特别是在编译器优化调用后) - 对于常见的LOB应用程序,Microsoft在C#中做出了许多非常务实的决策。请注意,例如 System.Action 在 .net 3.5 中只有 T4,然后 .net 4.0 根据真实世界的需求添加了一些重载,最高可达 T16。我想过去没有太多关于超高效的 string.Concat 的实际需求,可能因为人们已经使用 StringBuilders 来完成这项工作。 - Michael Stum
显示剩余5条评论

0
这是出于性能原因而做的。你实际上可以使用5个字符串参数来调用Concat方法,但是如果你查看生成的代码,它会运行接受数组的方法。同时添加字符串比串行添加更快。请参考下面的链接获取更多信息。

http://www.dotnetperls.com/string-concat


不幸的是,该页面没有显示Concat(String[])形式,因此无法进行直接比较。 - user2864740
@user2864740 如果您查看IL反汇编器上的五个字符串的注释,它指出没有五个参数重载,而是使用了params版本,即<code>Concat(string[])</code>构造函数。 - James Ralston

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接