Why use String.Format?
I can see a number of reasons:
Readability
string s = string.Format("Hey, {0} it is the {1}st day of {2}. I feel {3}!", _name, _day, _month, _feeling);
vs:
string s = "Hey," + _name + " it is the " + _day + "st day of " + _month + ". I feel " + feeling + "!";
Format Specifiers
(and this includes the fact you can write custom formatters)
string s = string.Format("Invoice number: {0:0000}", _invoiceNum);
vs:
string s = "Invoice Number = " + ("0000" + _invoiceNum).Substr(..... /*can't even be bothered to type it*/)
String Template Persistence
What if I want to store string templates in the database? With string formatting:
_id _translation
1 Welcome {0} to {1}. Today is {2}.
2 You have {0} products in your basket.
3 Thank-you for your order. Your {0} will arrive in {1} working days.
vs:
_id _translation
1 Welcome
2 to
3 . Today is
4 .
5 You have
6 products in your basket.
7 Someone
8 just shoot
9 the developer.
Is it better practice to use String.format over string Concatenation in Java?
I'd suggest that it is better practice to use String.format()
. The main reason is that String.format()
can be more easily localised with text loaded from resource files whereas concatenation can't be localised without producing a new executable with different code for each language.
If you plan on your app being localisable you should also get into the habit of specifying argument positions for your format tokens as well:
"Hello %1$s the time is %2$t"
This can then be localised and have the name and time tokens swapped without requiring a recompile of the executable to account for the different ordering. With argument positions you can also re-use the same argument without passing it into the function twice:
String.format("Hello %1$s, your name is %1$s and the time is %2$t", name, time)
c# string formatting
You picked too simple of an example.
String formatting:
- allows you to use the same variable multiple times:
("{0} + {0} = {1}", x, 2*x)
- automatically calls
ToString
on its arguments:("{0}: {1}", someKeyObj, someValueObj)
- allows you to specify formatting:
("The value will be {0:3N} (or {1:P}) on {2:MMMM yyyy gg}", x, y, theDate)
- allows you to set padding easily:
(">{0,3}<", "hi"); // ">hi <"
String.format() vs + operator
If you are looking for performance only I believe that using StringBuilder/StringBuffer
is the most efficient way to build strings. Even if the Java compiler is smart enough to translate most of String concatenations to StringBuilder
equivalent.
If you are looking for readability the String.format
thing is the much clearer I think, and this is what I use also unless I need to rely on high performance.
So if your main concern is not performance, meaning this code is not in a path that is called a lot, you may prefer to use String.format
as it gives a better idea of the resulting String (like you said).
Besides, using String.format
lets you use the format thing, which means you can use it for padding Strings, formatting numbers, dates, and so on, which would make the code even worse if using simple concatenation.
Edit for Chuu:
Using JAD, you can see that the following code:
public class Test {
public static void main(String[] args) {
String str = "a" + "b" + "c";
String str2 = "foo" + str + "bar" + str;
System.out.println(str2);
}
}
when decompiled will look like:
public class Test {
public static void main(String[] args) {
String str = "abc";
String str2 = new StringBuilder("foo").append(str).append("bar").append(str).toString();
System.out.println(str2);
}
}
Proof of that can also be found using the javap
utility that will show you the Java bytecode under a .class
file:
public static void main(java.lang.String[] args);
0 ldc <String "abc"> [16]
2 astore_1 [str]
3 new java.lang.StringBuilder [18]
6 dup
7 ldc <String "foo"> [20]
9 invokespecial java.lang.StringBuilder(java.lang.String) [22]
12 aload_1 [str]
13 invokevirtual java.lang.StringBuilder.append(java.lang.String) : java.lang.StringBuilder [25]
16 ldc <String "bar"> [29]
18 invokevirtual java.lang.StringBuilder.append(java.lang.String) : java.lang.StringBuilder [25]
21 aload_1 [str]
22 invokevirtual java.lang.StringBuilder.append(java.lang.String) : java.lang.StringBuilder [25]
25 invokevirtual java.lang.StringBuilder.toString() : java.lang.String [31]
28 astore_2 [str2]
29 getstatic java.lang.System.out : java.io.PrintStream [35]
32 aload_2 [str2]
33 invokevirtual java.io.PrintStream.println(java.lang.String) : void [41]
36 return
When is it better to use String.Format vs string concatenation?
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.
String.Format vs ToString()
I did a little benchmark in Linqpad:
void Main()
{
int iterations = 1000000;
decimal d = 12.0m;
var text = "";
var sw = Stopwatch.StartNew();
for (int i = 0; i < iterations; i++)
{
// 1. how I'd have done it
text = d.ToString();
}
sw.Stop();
sw.ElapsedMilliseconds.Dump("ToString()");
sw = Stopwatch.StartNew();
for (int i = 0; i < iterations; i++)
{
// 2. how I saw someone do it today
text = String.Format("{0}", d);
}
sw.Stop();
sw.ElapsedMilliseconds.Dump("Format");
}
ToString()
157
Format
264
ToString() looks consistently faster.
EDIT: I should point out, that on my PC 10 million "Format" operations only took 2.2 seconds. This looks very much like a micro-optimization, and unless what you're doing is extremely performance-critical, or iterative - it'd not worry about this too much.
String Interpolation vs String.Format
The answer is both yes and no. ReSharper
is fooling you by not showing a third variant, which is also the most performant. The two listed variants produce equal IL code, but the following will indeed give a boost:
myString += $"{x.ToString("x2")}";
Full test code
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Configs;
using BenchmarkDotNet.Diagnosers;
using BenchmarkDotNet.Diagnostics.Windows;
using BenchmarkDotNet.Running;
namespace StringFormatPerformanceTest
{
[Config(typeof(Config))]
public class StringTests
{
private class Config : ManualConfig
{
public Config() => AddDiagnoser(MemoryDiagnoser.Default, new EtwProfiler());
}
[Params(42, 1337)]
public int Data;
[Benchmark] public string Format() => string.Format("{0:x2}", Data);
[Benchmark] public string Interpolate() => $"{Data:x2}";
[Benchmark] public string InterpolateExplicit() => $"{Data.ToString("x2")}";
}
class Program
{
static void Main(string[] args)
{
var summary = BenchmarkRunner.Run<StringTests>();
}
}
}
Test results
| Method | Data | Mean | Gen 0 | Allocated |
|-------------------- |----- |----------:|-------:|----------:|
| Format | 42 | 118.03 ns | 0.0178 | 56 B |
| Interpolate | 42 | 118.36 ns | 0.0178 | 56 B |
| InterpolateExplicit | 42 | 37.01 ns | 0.0102 | 32 B |
| Format | 1337 | 117.46 ns | 0.0176 | 56 B |
| Interpolate | 1337 | 113.86 ns | 0.0178 | 56 B |
| InterpolateExplicit | 1337 | 38.73 ns | 0.0102 | 32 B |
New test results (.NET 6)
Re-ran the test on .NET 6.0.9.41905, X64 RyuJIT AVX2
.
| Method | Data | Mean | Gen0 | Allocated |
|-------------------- |----- |---------:|-------:|----------:|
| Format | 42 | 37.47 ns | 0.0089 | 56 B |
| Interpolate | 42 | 57.61 ns | 0.0050 | 32 B |
| InterpolateExplicit | 42 | 11.46 ns | 0.0051 | 32 B |
| Format | 1337 | 39.49 ns | 0.0089 | 56 B |
| Interpolate | 1337 | 59.98 ns | 0.0050 | 32 B |
| InterpolateExplicit | 1337 | 12.85 ns | 0.0051 | 32 B |
The InterpolateExplicit()
method is faster since we now explicitly tell the compiler to use a string
. No need to box the object to be formatted. Boxing is indeed very costly. Also, note that pre-NET6 we reduced the allocations a bit.
String.format() vs string concatenation performance
The second one will be even slower (if you look at the source code of String.format()
you will see why). It is just because String.format()
executes much more code than the simple concatenation. And at the end of the day, both code versions create 3 instances of String
. There are other reasons, not performance related, to use String.format()
, as others already pointed out.
Performance between String.format and StringBuilder
After doing a little test with StringBuilder
vs String.format
I understood how much time it takes each of them to solve the concatenation. Here the snippet code and the results
Code:
String name = "stackover";
String lName = " flow";
String nick = " stackoverflow";
String email = "stackoverflow@email.com";
int phone = 123123123;
//for (int i = 0; i < 10; i++) {
long initialTime1 = System.currentTimeMillis();
String response = String.format(" - Contact {name=%s, lastName=%s, nickName=%s, email=%s, phone=%d}",
name, lName, nick, email, phone);
long finalTime1 = System.currentTimeMillis();
long totalTime1 = finalTime1 - initialTime1;
System.out.println(totalTime1 + response);
long initialTime2 = System.currentTimeMillis();
final StringBuilder sb = new StringBuilder(" - Contact {");
sb.append("name=").append(name)
.append(", lastName=").append(lName)
.append(", nickName=").append(nick)
.append(", email=").append(email)
.append(", phone=").append(phone)
.append('}');
String response2 = sb.toString();
long finalTime2 = System.currentTimeMillis();
long totalTime2 = finalTime2 - initialTime2;
System.out.println(totalTime2 + response2);
//}
After of run the code several times, I saw that String.format
takes more time:
String.format: 46: Contact {name=stackover, lastName= flow, nickName= stackoverflow, email=stackoverflow@email.com, phone=123123123}
StringBuilder: 0: Contact {name=stackover, lastName= flow, nickName= stackoverflow, email=stackoverflow@email.com, phone=123123123}
String.format: 38: Contact {name=stackover, lastName= flow, nickName= stackoverflow, email=stackoverflow@email.com, phone=123123123}
StringBuilder: 0: Contact {name=stackover, lastName= flow, nickName= stackoverflow, email=stackoverflow@email.com, phone=123123123}
String.format: 51: Contact {name=stackover, lastName= flow, nickName= stackoverflow, email=stackoverflow@email.com, phone=123123123}
StringBuilder: 0: Contact {name=stackover, lastName= flow, nickName= stackoverflow, email=stackoverflow@email.com, phone=123123123}
But if I run the same code inside a loop, the result change.
String.format: 43: Contact {name=stackover, lastName= flow, nickName= stackoverflow, email=stackoverflow@email.com, phone=123123123}
StringBuilder: 0: Contact {name=stackover, lastName= flow, nickName= stackoverflow, email=stackoverflow@email.com, phone=123123123}
String.format: 1: Contact {name=stackover, lastName= flow, nickName= stackoverflow, email=stackoverflow@email.com, phone=123123123}
StringBuilder: 0: Contact {name=stackover, lastName= flow, nickName= stackoverflow, email=stackoverflow@email.com, phone=123123123}
String.format: 1: Contact {name=stackover, lastName= flow, nickName= stackoverflow, email=stackoverflow@email.com, phone=123123123}
StringBuilder: 0: Contact {name=stackover, lastName= flow, nickName= stackoverflow, email=stackoverflow@email.com, phone=123123123}
The first time String.format
runs it takes more time, after of that the time is shorter even though it does not become constant as a result of StringBuilder
As @G.Fiedler said: "String.format
has to parse the format string..."
With these results it can be said that StringBuilder
is more efficient thanString.format
Related Topics
Asp:Fileupload Edit "No File Selected" Message
HTML Table (Text) to Image Using C#
Using C# to Dynamically Generate CSS Files
Send Push to Android by C# Using Fcm (Firebase Cloud Messaging)
Adding Distance to a Gps Coordinate
How to Manage Files on an Mtp Portable Device
Xamarin iOS Memory Leaks Everywhere
How to Add a Custom View to a Xib File Defined View in Monotouch
Executing R Script Programmatically
In Ruby, What Is the Equivalent to an Interface in C#
Passing Dynamic Object to C# Method Changes Return Type
Why Does It Appear That My Random Number Generator Isn't Random in C#
Timeout Pattern - How Bad Is Thread.Abort Really
When I Post Back to My Controller All Values for My Model Are Null
Error on If Statement - Cannot Implicitly Convert Type to 'Bool'