I've got a small piece of code that is parsing an index value to determine a cell input into Excel. It's got me thinking...
What's the difference between
xlsSheet.Write("C" + rowIndex.ToString(), null, title);
and
xlsSheet.Write(string.Format("C{0}", rowIndex), null, title);
Is one "better" than the other? And why?
Before C# 6
To be honest, I think the first version is simpler - although I'd simplify it to:
xlsSheet.Write("C" + rowIndex, null, title);
I suspect other answers may talk about the performance hit, but to be honest it'll be minimal if present at all - and this concatenation version doesn't need to parse the format string.
Format strings are great for purposes of localisation etc, but in a case like this concatenation is simpler and works just as well.
With C# 6
String interpolation makes a lot of things simpler to read in C# 6. In this case, your second code becomes:
xlsSheet.Write($"C{rowIndex}", null, title);
which is probably the best option, IMO.
My initial preference (coming from a C++ background) was for String.Format. I dropped this later on due to the following reasons:
- String concatenation allows for null values, String.Format
does not. Writing "s1 + null + s2
" does not break, it just treats the null value as String.Empty. Well, this may depend on your specific scenario - there are cases where you'd like an error instead of silently ignoring a null FirstName. However even in this situation I personally prefer checking for nulls myself and throwing specific errors instead of the standard ArgumentNullException I get from String.Format.
Idea is the .NET compiler is smart enough to convert this piece of code:
public static string Test(string s1, int i2, int i3, int i4,
string s5, string s6, float f7, float f8)
{
return s1 + " " + i2 + i3 + i4 + " ddd " + s5 + s6 + f7 + f8;
}
to this:
public static string Test(string s1, int i2, int i3, int i4,
string s5, string s6, float f7, float f8)
{
return string.Concat(new object[] { s1, " ", i2, i3, i4,
" ddd ", s5, s6, f7, f8 });
}
What happens under the hood of String.Concat is easy to guess (use Reflector). The objects in the array get converted to their string via ToString(). Then the total length is computed and only one string allocated (with the total length). Finally, each string is copied into the resulting string via wstrcpy in some unsafe piece of code.
Reasons String.Concat
is way faster? Well, we can all have a look what String.Format
is doing - you'll be surprised at the amount of code required to process the format string. On top of this (I've seen comments regarding the memory consumption), String.Format
uses a StringBuilder internally. Here's how:
StringBuilder builder = new StringBuilder(format.Length + (args.Length * 8));
So for every passed argument, it reserves 8 characters. If the argument is a one-digit value, then too bad, we have some wasted space. If the argument is a custom object returning some long text on ToString()
, then there might be even some reallocation needed (worst-case scenario, of course).
Compared to this, the concatenation only wastes the space of the object array (not too much, taking into account it's an array of references). There's no parsing for format specifiers and no intermediary StringBuilder. The boxing/unboxing overhead is present in both methods.
The only reason I'd go for String.Format is when localization is involved. Putting format strings in resources allows you to support different languages without messing with the code (think about scenarios where formatted values change order depending on the language, i.e. "after {0} hours and {1} minutes" may look quite different in Japanese :).
To sum up my first (and quite long) post:
ToString()
callsToString()
calls yourself to avoid boxing (I'm somewhat biased towards readability) - same as first option in your questionString.Format()
has an edge.