The primary motivation for solving this implementation is performance.
As you rightly noted, there can only be two:
public static string Concat(params object[] args);
public static string Concat<T>(IEnumerable<T> values);
# "params enumerable", IEnumerable<T> T[] - . .
, .
string x = Foo();
string y = Bar();
string z = x + y;
? ToString codegen'd
string x = Foo();
string y = Bar();
object[] array = new string[2];
array[0] = x;
array[1] = y;
string z = string.Concat(array);
: . , . , , .. , ..
; , , , . , , , , , , : .
, . , Concat.
- - - , . , ? . ToString ? , . null, ToString.
, . ToString , , , . , . , , , ..
, , .
. ?
, , :
static string Concat(string, string)
:
string x = Foo();
string y = Bar();
string z = string.Concat(x, y);
, , , . , ToString , , , , ..
, : , params, , .
, . . , , , , . , ; , .
, , 2006 .
https://ericlippert.com/2013/06/17/string-concatenation-behind-the-scenes-part-one/