Question:
Viewing a code here on SOpt, I noticed the use of the symbol "$" and I was in doubt about its use.
- What is the "$" symbol before a string ?
- What is it for?
- Why use it?
Example
using static System.Console;
public class Program {
public static void Main() {
var texto = " Hello World ";
WriteLine($"Corta o fim: |{texto.TrimEnd()}|");
WriteLine($"Corta o início: |{texto.TrimStart()}|");
WriteLine($"Corta ambos: |{texto.Trim()}|");
WriteLine($"Corta tudo: |{texto.Replace(" ", "")}|");
}
}
Answer:
This is called string interpolation .
In C# 6 there is this symbol to indicate a special condition of that string literal. With string interpolation, we can use a variable or an expression inside the string . For this the compiler needs to understand that this is being used in it, that is, that it is a special literal. Without the symbol the compiler will interpret the literal as any text and will not take any specific action.
It is a way to avoid string concatenation. It also prevents passing an argument to the string to be formatted:
WriteLine($"Contei {x} vezes");
WriteLine("Contei {0} vezes", x);
WriteLine("Contei " + x.ToString() + " vezes");
See it working on ideone . And in .NET Fiddle . I also put it on GitHub for future reference .
Comparing the shapes
What is the best way?
Concatenation is certainly the worst and should be avoided, there are or were few cases where it was useful. One advantage it had is that it was often faster to concatenate than to format a string by putting the content inside.
The syntax difference is more evident outside of Write
:
var texto = $"Contei {x} vezes";
var texto = string.Format("Contei {0} vezes", x);
The first is simpler and keeps the reading flow. You see the expression that will be used to insert within the text at the exact place where it will be inserted. With formatting (second example) you have to look ahead to what argument to use. And if you have several, use some argument over and over again, you'll have to keep counting to find out what goes where.
Note that the compiler evaluates what is inside the interpolation. It is not treated as a part of the text but as part of the code. Any valid C# code can be used.
She doesn't solve everything
The second, the format string , is not discarded. It has the advantage of being resolved at runtime. It is often what you want. A typical example is internationalization messages. You may have texts that may be in multiple languages. Inside this text you must enter a variable that the application will place when executing. This will only be resolved at runtime, so text interpolation is ruled out.
Let's say you have the following text in an external file or database: Minha idade é {idade}
And there is a method that gets it in the file, like this:
var idade = 25;
var exemplo = GetLocalText("My age is"); //retorna o texto "Minha idade é {idade}"
var texto = $exemplo; //isto não funciona, não é um literal.
This exemplo
variable text coming from outside the application is not known to the compiler. The idade
inside the text was never compiled, so the variable cannot be put in place of this text.
The solution would be to store the string differently ( Minha idade é {0}
) and pass an argument to it.
var idade = 25;
var exemplo = GetLocalText("My age is"); //retorna o texto acima
var texto = string.Format(exemplo, idade); //produzirá "Minha idade é 25".
Of course if you are going to repeat an expression within the text it is probably worth executing it before storing it in a variable and using just the variable.
extra information
Documentation with example and other forms of formatting .
An example of how it looks better together with other ASP.NET Core features.
Old one:
@Html.ActionLink("Hello " + User.Identity.GetUserName() + "!", "Index",
"Manage", routeValues: null, htmlAttributes: new { title = "Manage" })
New:
<a asp-controller="Manage" asp-action="Index" title="Manage">Hello @User.GetUserName()!</a>
I put it on GitHub for future reference .
To obtain this result internally there is an interpolation.
In future C# version (maybe 10) should have constant string interpolation which is an optimization I've been waiting for since 6.