String.FormatはStringBuilder内部的に使用します。論理的には、オーバーヘッドが大きくなるため、パフォーマンスが少し低下するという考えにつながります。ただし、単純な文字列連結は、2つの文字列の間に1つの文字列を注入する最も高速な方法です。この証拠は、数年前の彼の最初のパフォーマンスクイズでRico Marianiによって示されました。単純な事実は、連結は...文字列の部分の数がわかっている場合(制限なしに... 1,000の部分を連結することができます...常に1000の部分を知っている限り)...は、StringBuilderまたはString よりも常に速いということです。フォーマット。これらは、単一のメモリ割り当てと一連のメモリコピーで実行できます。ここに証明があります
そして、いくつかのString.Concatメソッドの実際のコードは次のとおりです。最終的には、ポインタを使用してメモリをコピーするFillStringCheckedを呼び出します(Reflectorで抽出)。
public static string Concat(params string[] values)
{
    int totalLength = 0;
    if (values == null)
    {
        throw new ArgumentNullException("values");
    }
    string[] strArray = new string[values.Length];
    for (int i = 0; i < values.Length; i++)
    {
        string str = values[i];
        strArray[i] = (str == null) ? Empty : str;
        totalLength += strArray[i].Length;
        if (totalLength < 0)
        {
            throw new OutOfMemoryException();
        }
    }
    return ConcatArray(strArray, totalLength);
}
public static string Concat(string str0, string str1, string str2, string str3)
{
    if (((str0 == null) && (str1 == null)) && ((str2 == null) && (str3 == null)))
    {
        return Empty;
    }
    if (str0 == null)
    {
        str0 = Empty;
    }
    if (str1 == null)
    {
        str1 = Empty;
    }
    if (str2 == null)
    {
        str2 = Empty;
    }
    if (str3 == null)
    {
        str3 = Empty;
    }
    int length = ((str0.Length + str1.Length) + str2.Length) + str3.Length;
    string dest = FastAllocateString(length);
    FillStringChecked(dest, 0, str0);
    FillStringChecked(dest, str0.Length, str1);
    FillStringChecked(dest, str0.Length + str1.Length, str2);
    FillStringChecked(dest, (str0.Length + str1.Length) + str2.Length, str3);
    return dest;
}
private static string ConcatArray(string[] values, int totalLength)
{
    string dest = FastAllocateString(totalLength);
    int destPos = 0;
    for (int i = 0; i < values.Length; i++)
    {
        FillStringChecked(dest, destPos, values[i]);
        destPos += values[i].Length;
    }
    return dest;
}
private static unsafe void FillStringChecked(string dest, int destPos, string src)
{
    int length = src.Length;
    if (length > (dest.Length - destPos))
    {
        throw new IndexOutOfRangeException();
    }
    fixed (char* chRef = &dest.m_firstChar)
    {
        fixed (char* chRef2 = &src.m_firstChar)
        {
            wstrcpy(chRef + destPos, chRef2, length);
        }
    }
}
それで:
string what = "cat";
string inthehat = "The " + what + " in the hat!";
楽しい!