-2

I have 2 codes in C# 6.0:

Sample 1:

string bar;
// ... some code setting bar.
var foo =
    "Some text, " +
    $"some other {bar}, " +
    "end text.";

Sample 2:

string bar;
// ... some code setting bar.
var foo =
    $"Some text, " +
    $"some other {bar}, " +
    $"end text.";

Obviously both codes generate the same result regardless of aesthetic differences.

Question:
Is there a performance difference between both? In other words, are both cases compiled to the same?

EDIT:
Some important comments was posted that I find useful to replay to make a clarification of the topic in this question.

The second one is horrible. Don't use the string interpolation symbol ($) on strings that aren't interpolated. It will be confusing for anyone else looking at the code (or future, more experienced you)

Thanks for the tip, it's very appreciated, although I have to argue that what you said is a aesthetic argumentation. Even this code been as ugly as you said, even if should never been used, I still think is useful discuss possible performances differences that It MAY generated.

@communityMember1: It doesn't affect performance of the code at runtime.
@communityMember2: That is not true. Interpolated string is syntactic sugar for calling string.Format, which has to be called (and thus affecting performance).

Maybe to avoid further discussion, we should reinforce the answers and comments based on some documentation or even an empirical proof (like the result of a compilation).

Jonny Piazzi
  • 3,684
  • 4
  • 34
  • 81
  • What about that {bar}? is it going to be interpolated? – Bruno Avelar Oct 05 '17 at 17:20
  • You could do benchmarks or compare the IL to find out the answer. – Jeroen Vannevel Oct 05 '17 at 17:20
  • 3
    The second one is horrible. Don't use the string interpolation symbol (`$`) on strings that aren't interpolated. It will be confusing for anyone else looking at the code (or future, more experienced you) – maccettura Oct 05 '17 at 17:20
  • 2
    Using $ is s syntactic sugar. It doesn't affect performance of the code at runtime. – Chetan Oct 05 '17 at 17:20
  • @ChetanRanpariya That is not true. Interpolated string is syntactic sugar for calling `string.Format`, which has to be called (and thus affecting performance). – Zereges Oct 05 '17 at 17:21
  • @Zereges performance wise it should not make a difference. The compiler will recognize that while the string is prefixed with `$`, if it lacks an expression in brackets `{ }` it will _not_ perform a string.format. You can check the IL yourself. OP's second example wont be worse performance, its just awful and makes zero sense. – maccettura Oct 05 '17 at 17:23
  • 4
    @Zereges look at the compiled IL [here](https://pastebin.com/F2TyHCv6) – maccettura Oct 05 '17 at 17:27
  • Question edited and answered. – Jonny Piazzi Oct 05 '17 at 18:00
  • 4
    @JonnyPiazzi `"This is totally your opinion, I have a team here with 10 senior C# developers, all agreed that the second one is more legible."` -- In that case I'm pretty concerned – maccettura Oct 05 '17 at 18:02
  • So, I'm sure this is supposed to be an over-simplified example, but why not `var foo = $"Some text, some other {bar}, end text.";`? – crashmstr Oct 05 '17 at 18:25
  • "You need to provide proof what are you saying." The proof is in the IL, which you, yourself, can observe. –  Oct 05 '17 at 18:45
  • The questions asks if there is a "problem (performance or others)" with using `$""` for strings that contain nothing to interpolate, and yet when someone points out such a potential "other" problem it's dismissed as "totally your opinion". So, therefore, this is an opinion-based question and should be closed? Also, I don't think asserting which code variant is more "beautiful" really adds anything to the question. That seems like it will do nothing but attract opinion-based comments either for or against, and if you're acknowledging it's purely opinion then why include it in the question? – Lance U. Matthews Oct 05 '17 at 18:48
  • 2
    @BACON I'm with you. The question started out about performance but the OP quickly made it about which looks better. Why even respond to peoples opinions? Why bother disagreeing when that isn't the point of the question? In the end, the question devolved into a pissing contest over who likes what (I suppose maccettura is wrong because **TEN** senior devs disagree? How is this *remotely* relevant to performance?). Original question was fine. Current question is about opinions. So I'm voting to close. –  Oct 05 '17 at 18:55
  • Same question about string interpolation also within the .NET ecosystem: [Powershell single quote vs double quote](https://stackoverflow.com/q/17491903/150605) – Lance U. Matthews Oct 05 '17 at 18:55
  • @BACON The OP also asks about performance, which is a legitimate non-opinion based question that I found useful. Also, there is a way to answer a subjective question objectively. Don't state your opinion but state why you have your opinion. That is informative and it allows for your opinion's basis to be challenged or it's premise to be modified with another premise. The issue isn't necessarily that a question is subjective but that the premises of a conclusion are explored. – u8it Oct 05 '17 at 18:56
  • @Amy see my comment above and also, the 10 senior engineer's point was an appeal to credibility. That's fine, SO has an appeal to credibility called reputation. The OP is making the point that this question is relevant to 10 people. – u8it Oct 05 '17 at 18:57
  • @u8it I agree that asking about the performance implications of string interpolation is a legitimate question. However, the body of the question very quickly strayed into a non-performance, opinion-based aspect of the code. If that were removed, I think this could be a good question. Then again, part of the value of StackOverflow is getting many eyeballs on what you're proposing to do so someone can chime in with "By the way, you should _really_ consider x, y, and z before you go down that road", so I wouldn't be surprised if the readability, clarity, etc. issues were raised, regardless. – Lance U. Matthews Oct 05 '17 at 19:26
  • 2
    @BACON Can I just say I think it's great that BACON and u8it (you ate it) are having a conversion. – u8it Oct 05 '17 at 19:51

4 Answers4

6

The $ creates an interpolated string which is the same as using String.Format. If you use + with string literals then the compiler optimizes the code to avoid concatenation all together. The use of interpolated strings might prevent this optimization.

Edit


Performance and Literal Optimization Test

Ok, well I just tested this and there doesn't seem to be any performance issue. Apparently the compiler ignores $ and doesn't use String.Format if no {} are present. My test results are shown below for 6 million loops of constructing a 50 length string.

  • String.Format: 23700 ms
  • $"a{null}" with + : 22650 ms
  • $"a" with + : 13 ms
  • "a" with +: 13 ms
  • "a" concatenated with +: 700 ms

Also, there's no difference looking at the IL. So performance wise, the code you posted is executed and optimized the same, the $ gets ignored and is only a factor when {} are used.

Syntax

Of course there can be debate about if that is good syntax or not. I can think of arguments for and against.

Pros

  • It's easier to add a new argument if $ is already present
  • It's easier to move an argument between lines of a multi-line literal
  • It provides consistency between lines of a multi-line literal

Cons

  • It looks different... principal of least astonishment.
  • Why add syntax that isn't being used?
  • It doesn't make the inserted variable obvious

For me, the tilting point is that I see $ and expect to see a {} and an argument. It causes cognitive dissonance if I don't see what I expect to see. On the other hand, I can imagine situations where the fluidity it provides might out way this. It's probably far to say it depends on the development group and objectives.

u8it
  • 3,956
  • 1
  • 20
  • 33
2

Look at the IL:

First code:

var bar = "a";
var foo = "b" + $"{bar}";

First IL:

IL_0000:  nop         
IL_0001:  ldstr       "a"
IL_0006:  stloc.0     // bar
IL_0007:  ldstr       "b"
IL_000C:  ldstr       "{0}"
IL_0011:  ldloc.0     // bar
IL_0012:  call        System.String.Format
IL_0017:  call        System.String.Concat
IL_001C:  stloc.1     // foo
IL_001D:  ret         

Second code:

var bar = "a";
var foo = $"b" + $"{bar}";

Second IL:

IL_0000:  nop         
IL_0001:  ldstr       "a"
IL_0006:  stloc.0     // bar
IL_0007:  ldstr       "b"
IL_000C:  ldstr       "{0}"
IL_0011:  ldloc.0     // bar
IL_0012:  call        System.String.Format
IL_0017:  call        System.String.Concat
IL_001C:  stloc.1     // foo
IL_001D:  ret         

Conclusion:

There is no compiled differences between the both codes.

PS: (IL generated by Linqpad 5.22.02).

Jonny Piazzi
  • 3,684
  • 4
  • 34
  • 81
  • There is no performance difference, but as far as syntax goes. You should absolutely not use the string interpolation sign on strings that are not interpolated, its confusing and silly. – maccettura Oct 05 '17 at 18:00
1

This was pretty easy to do some simple diagnostics with. Maccettura shows in the comment that that there is no difference when it gets compiled as it only called String.Format once for each string regardless of the extra interpolation but this test will back it up as well.

int rounds = 50;
int timesToCreateString = 50000;
Stopwatch sw = new Stopwatch();
double first = 0;
double second = 0;
for (int i = 0; i < rounds; i++)
{
    sw.Start();
    for (int bar = 0; bar < timesToCreateString; bar++)
    {
        var foo = "Some text, " +
                 $"some other {bar}, " +
                  "end text.";
    }
    sw.Stop();
    first += sw.ElapsedTicks;
    sw.Reset();
    sw.Start();
    for (int bar = 0; bar < timesToCreateString; bar++)
    {                
        var foo = $"Some text, " +
                  $"some other {bar}, " +
                  $"end text.";
    }
    sw.Stop();
    second += sw.ElapsedTicks;
    sw.Reset();
}
Console.WriteLine("Average first test: " + first / rounds);
Console.WriteLine("Average second test: " + second / rounds);
Console.ReadKey();
// program ran 3 times and results.
//Average first test: 54822.04
//Average second test: 55083.86

//Average first test: 54317.66
//Average second test: 54807.8

//Average first test: 49873.12
//Average second test: 48264.36
Sam Marion
  • 690
  • 1
  • 4
  • 17
  • There literally _is no difference_. Your diagnostic results are not indicative of anything because they will always run at different lengths even if they were the same exact code. Look at how it compiles down to IL, they are **identical** – maccettura Oct 05 '17 at 17:45
  • My results show what you are saying. I should probably have not used the word negligible so I'll edit that out but my code just shows how to use diagnostic features to test. I should probably also include how it compiles to show it doesn't matter – Sam Marion Oct 05 '17 at 17:48
  • Thanks for pointing that out I edited my answer how did you go about getting how it compiled down to IL if you don't mind sharing. – Sam Marion Oct 05 '17 at 17:52
  • You can use LINQ Pad – maccettura Oct 05 '17 at 17:58
  • 1
    Cool, thanks will be sure to use this in the future! – Sam Marion Oct 05 '17 at 18:03
  • 1
    It's pretty neat for quick POC, plus the IL feature is really cool. I don't use it often but in cases where I need IL its really valuable (plus its free). – maccettura Oct 05 '17 at 18:04
  • I've come across [tryroslyn.azurewebsites.net](http://tryroslyn.azurewebsites.net/)/[sharplab.io](https://sharplab.io/) in a lot of other answers, so that's what I use, too, when I want to [examine and share what IL the compiler generates](https://sharplab.io/#v2:C4LglgNgNAJiDUAfAAgBgATIIwG4CwAUMgMyYBM6AwugN6HoOanIAs6AsgBQCUt9jAgG4BDAE7oARmPQBedACJgAUwDOwefgICh0gGYB7fVlkKAyvoC2S9MoAewKAvTx+2xgBJ5Ky9f3AAFkriNFKiAL6O8s6ubgpKAHYwNkr2AHQahACQmSLiBvoUcp7mVsn2kdFasQye3qV+gcGhEU4uVdWeCUl2wOmaAmGEYUA===). – Lance U. Matthews Oct 05 '17 at 18:26
1

You can choose whatever you like. It is true the $ translates to string.format (see https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/interpolated-strings ) but the compiler is smart enough to filter out code that isn't formatted.

realbart
  • 3,497
  • 1
  • 25
  • 37