I'm going to add an example now to illustrate how the compiler treats the two, because there seems to be a lot of confusion in some of the other answers (edit: note that much of these confusions have now been deleted/edited away):
bool value = true;
int channel = 1;
String s = String.Format(":Channel{0}:Display {1}", channel,
value ? "ON" : "OFF");
The last line is compiled as:
String s = String.Format(":Channel{0}:Display {1}",
new object[2] {(object)channel, value ? "ON" : "OFF")};
note interestingly the creation of an array and a "box" for int channel
, and of course the extra parsing required to find {0}
/ {1}
.
Now Number 2:
bool value = true;
String channel = "1";
string s = ":Channel" + channel + ":Display " + (value ? "ON" : "OFF");
The last line is compiled as:
string s = string.Concat(":Channel", channel, ":Display ", value ? "ON" : "OFF");
here there is no array, no box (channel
is now a string), and no parsing. The overload is public static string string.Concat(string,string,string,string)
; string.Concat
is implemented very efficiently, pre-allocating a right-sized string in advance then over-writing, etc.
In most code, either is fine. The second version is technically more efficient (no box, no array, no parsing), but is a major pain if you ever want to internationalize later. In most applications you will not notice any difference between the two. The parsing is fast, and the box / array are collected cheaply as gen-zero objects. But cheap is not free.