O que $ significa antes de uma string?

250

Eu ia usar string literal, mas eu digitei por engano em $vez de @.

Mas o compilador não me deu nenhum erro e foi compilado com êxito.

Eu quero saber o que é e o que faz. Eu procurei, mas não consegui encontrar nada.

No entanto, não é como uma string literal porque não posso escrever:

string str = $"text\";

Alguém sabe o que $antes significa string em C #.

string str = $"text";

Estou usando o CTP do Visual studio 2015.

M.kazem Akhgary
fonte

Respostas:

418

$é uma abreviação de String.Formate é usado com interpolações de strings, que é um novo recurso do C # 6. Como usado no seu caso, ele não faz nada, assim como string.Format()não faria nada.

Isso ocorre quando usado para criar strings com referência a outros valores. O que anteriormente tinha que ser escrito como:

var anInt = 1;
var aBool = true;
var aString = "3";
var formated = string.Format("{0},{1},{2}", anInt, aBool, aString);

Agora se torna:

var anInt = 1;
var aBool = true;
var aString = "3";
var formated = $"{anInt},{aBool},{aString}";

Há também uma forma alternativa - menos conhecida - de interpolação de string usando $@ (a ordem dos dois símbolos é importante). Ele permite que os recursos de uma @""sequência sejam misturados $""para suportar interpolações de sequência sem a necessidade de \\toda a sequência. Portanto, as duas linhas a seguir:

var someDir = "a";
Console.WriteLine($@"c:\{someDir}\b\c");

irá produzir:

c:\a\b\c
David Arno
fonte
29
Observe que ele não está realmente usando o String.Format, mas é um recurso baseado em compilador, e não em tempo de execução.
Shahar Prish
2
Nota menor que eu aprendi hoje, se você usar $@, então você é forçado a escapar do "personagem usando "". Este não é o caso quando você usa apenas $.
Flater
3
@ Flater Isso não tem nada a ver com o símbolo $. Esse é o mesmo comportamento que era antes da existência do símbolo $.
BVernon
2
Para o seu ponto sobre a ordem dos símbolos verbatim (@) e interpolação ($) ser importante, isso está sendo corrigido no C # 8 para que a ordem não seja mais importante. Veja: devsanon.com/uncategorized/…
elkaz 02/02/19
38

Ele cria uma cadeia de caracteres interpolada .

Do MSDN

Usado para construir strings. Uma expressão de cadeia interpolada se parece com uma cadeia de modelo que contém expressões. Uma expressão de cadeia interpolada cria uma cadeia de caracteres substituindo as expressões contidas pelas representações de ToString dos resultados das expressões.

ex:

 var name = "Sam";
 var msg = $"hello, {name}";

 Console.WriteLine(msg); // hello, Sam

Você pode usar expressões dentro da sequência interpolada

 var msg = $"hello, {name.ToLower()}";
 Console.WriteLine(msg); // hello, sam

O bom disso é que você não precisa se preocupar com a ordem dos parâmetros, como faz String.Format.

  var s = String.Format("{0},{1},{2}...{88}",p0,p1,..,p88);

Agora, se você deseja remover alguns parâmetros, é necessário atualizar todas as contagens, o que não é mais o caso.

Observe que o bom e velho string.formatainda é relevante se você deseja especificar informações culturais em sua formatação .

Sleiman Jneidi
fonte
Observe que você provavelmente ainda poderá usar $e especificar informações de cultura se converter seus dados em string dentro da $expressão usando a cultura correta, por exemplo {somevar.ToString(...,[Insert culture info here])},.
JRH
18

Código de exemplo

public class Person {
    public String firstName { get; set; }
    public String lastName { get; set; }
}

// Instantiate Person
var person = new Person { firstName = "Albert", lastName = "Einstein" };

// We can print fullname of the above person as follows
Console.WriteLine("Full-Name - " + person.firstName + " " + person.lastName);
Console.WriteLine("Full-Name - {0} {1}", person.firstName, person.lastName);
Console.WriteLine($"Full-Name - {person.firstName} {person.lastName}");

Resultado

Full-Name - Albert Einstein
Full-Name - Albert Einstein
Full-Name - Albert Einstein

É seqüências de caracteres interpoladas . Você pode usar uma cadeia de caracteres interpolada em qualquer lugar em que possa usar uma cadeia de caracteres literal. Ao executar o programa, o código seria executado com a literal de cadeia interpolada, o código calcula uma nova literal de cadeia avaliando as expressões de interpolação. Esse cálculo ocorre sempre que o código com a sequência interpolada é executado.

O exemplo a seguir produz um valor de sequência em que todos os valores de interpolação de sequência foram calculados. É o resultado final e tem o tipo string. Todas as ocorrências de chaves duplas (“{{“ and “}}”)são convertidas em uma única chave.

string text = "World";
var message = $"Hello, {text}";

Depois de executar acima de 2 linhas, a variável messagecontém "Olá, Mundo".

Console.WriteLine(message); // Prints Hello, World

Referência - MSDN

Saveendra Ekanayake
fonte
10

Recurso legal. Eu só quero salientar a importância do melhor que o string.format, se não for aparente para algumas pessoas.

Eu li alguém dizendo ordem string.format como "{0} {1} {2}" para corresponder aos parâmetros. Você não é obrigado a solicitar "{0} {1} {2}" em string.format, também pode fazer "{2} {0} {1}". No entanto, se você tiver muitos parâmetros, como 20, realmente deseja sequenciar a sequência para "{0} {1} {2} ... {19}". Se for uma bagunça embaralhada, será difícil alinhar seus parâmetros.

Com $, você pode adicionar parâmetros em linha sem contar seus parâmetros. Isso torna o código muito mais fácil de ler e manter.

A desvantagem de $ é que você não pode repetir o parâmetro na string facilmente, é necessário digitá-lo. Por exemplo, se você está cansado de digitar System.Environment.NewLine, pode executar string.format ("... {0} ... {0} ... {0}", System.Environment.NewLine), mas, em $, você deve repetir. Você não pode fazer $ "{0}" e passá-lo para string.format porque $ "{0}" retorna "0".

Na nota lateral, eu li um comentário em outra tática duplicada. Eu não poderia comentar, então aqui está. Ele disse que

string msg = n + " sheep, " + m + " chickens";

cria mais de um objeto de sequência. Isso não é verdade, na verdade. Se você fizer isso em uma única linha, ele criará apenas uma sequência e será colocada no cache da sequência.

1) string + string + string + string;
2) string.format()
3) stringBuilder.ToString()
4) $""

Todos eles retornam uma sequência e apenas criam um valor no cache.

Por outro lado:

string+= string2;
string+= string2;
string+= string2;
string+= string2;

Cria 4 valores diferentes no cache, porque existem 4 ";".

Assim, será mais fácil escrever código como o seguinte, mas você criaria cinco seqüências interpoladas, conforme Carlos Muñoz corrigiu:

string msg = $"Hello this is {myName}, " +
  $"My phone number {myPhone}, " +
  $"My email {myEmail}, " +
  $"My address {myAddress}, and " +
  $"My preference {myPreference}.";

Isso cria uma única sequência no cache, enquanto você tem um código de leitura muito fácil. Não tenho certeza sobre o desempenho, mas estou certo de que a Microsoft irá otimizá-lo se ainda não o estiver fazendo.

BoBoDev
fonte
1
Seu último exemplo está errado: Na verdade, você está criando duas cadeias: uma da cadeia interpolada e outra do restante das cadeias. Observe que apenas aquele com {myName} é interpolado, os outros não funcionam conforme o esperado.
Carlos Muñoz
1
E se você anexar $ às 5 strings, ele criará 5 strings interpoladas, cada uma com a sua String.Format()e concatenadas em tempo de execução com String.Concat. Por isso, é melhor que você não dividi-lo em várias linhas
Carlos Muñoz
1
Você está certo @Carlos Muñoz, eu o corrigi. Obrigado por pegar o erro.
BoBoDev
8

Observe que você também pode combinar os dois, o que é bem legal (embora pareça um pouco estranho):

// simple interpolated verbatim string
WriteLine($@"Path ""C:\Windows\{file}"" not found.");
Marsze
fonte
5
Se você pudesse decidir a ordem em que digitou $@ou @$. Infelizmente só pode ser$@
Bauss
2
@ Bauss Isso faz sentido. @define como representar a cadeia literal. $é um atalho para string.Format. Pense nisso como$(@"");
marsze
Não é realmente um atalho para string.Format. É interessante apresentar um valor que é analisado como a string.Format, portanto faz sentido parcialmente, mas não inteiramente.
Bauss 18/01/19
3
Só estou dizendo que $é basicamente uma chamada de função implícita, enquanto @faz parte do literal, assim como mno literal decimal. É por isso que existe apenas uma ordem lógica.
marsze
2
Eu sei que isso foi feito aqui apenas para demonstrar $, mas por uma questão de compatibilidade máxima e não por codificação permanente, se o separador de diretório é '/' ou '\', além de evitar a inevitável confusão que causa uma barra dupla ou uma barra ausente onde deveria foram um, eu recomendo usar em Path.Combine()vez de usar concatenações de string ao trabalhar com diretórios e arquivos.
JRH
6

É mais conveniente do que string.Format e você pode usar o intellisense aqui também.

insira a descrição da imagem aqui

E aqui está o meu método de teste:

[TestMethod]
public void StringMethodsTest_DollarSign()
{
    string name = "Forrest";
    string surname = "Gump";
    int year = 3; 
    string sDollarSign = $"My name is {name} {surname} and once I run more than {year} years."; 
    string expectedResult = "My name is Forrest Gump and once I run more than 3 years."; 
    Assert.AreEqual(expectedResult, sDollarSign);
}
GorkemHalulu
fonte
6

Significa interpolação de string.

Ele o protegerá porque está adicionando proteção ao tempo de compilação na avaliação da string.

Você não receberá mais uma exceção com string.Format("{0}{1}",secondParamIsMissing)

prata
fonte
6

O exemplo a seguir destaca várias vantagens do uso de seqüências de caracteres interpoladas em relação string.Format()à limpeza e legibilidade. Também mostra que o código dentro {}é avaliado como qualquer outro argumento de função, como faria se string.Format()estivéssemos sendo chamados.

using System;

public class Example
{
   public static void Main()
   {
      var name = "Horace";
      var age = 34;
      // replaces {name} with the value of name, "Horace"
      var s1 = $"He asked, \"Is your name {name}?\", but didn't wait for a reply.";
      Console.WriteLine(s1);

      // as age is an integer, we can use ":D3" to denote that
      // it should have leading zeroes and be 3 characters long
      // see https://docs.microsoft.com/en-us/dotnet/standard/base-types/how-to-pad-a-number-with-leading-zeros
      //
      // (age == 1 ? "" : "s") uses the ternary operator to 
      // decide the value used in the placeholder, the same 
      // as if it had been placed as an argument of string.Format
      //
      // finally, it shows that you can actually have quoted strings within strings
      // e.g. $"outer { "inner" } string"
      var s2 = $"{name} is {age:D3} year{(age == 1 ? "" : "s")} old.";
      Console.WriteLine(s2); 
   }
}
// The example displays the following output:
//       He asked, "Is your name Horace?", but didn't wait for a reply.
//       Horace is 034 years old.
Pažout
fonte
6

A sintaxe $ é legal, mas com uma desvantagem.

Se você precisar de algo como um modelo de seqüência de caracteres, que seja declarado no nível da classe como campo ... bem em um local como deveria ser.

Então você tem que declarar as variáveis ​​no mesmo nível ... o que não é muito legal.

É muito melhor usar a string.Format sintaxe para esse tipo de coisa

class Example1_StringFormat {
 string template = $"{0} - {1}";

 public string FormatExample1() {
   string some1 = "someone";
   return string.Format(template, some1, "inplacesomethingelse");
 }

 public string FormatExample2() {
   string some2 = "someoneelse";
   string thing2 = "somethingelse";
   return string.Format(template, some2, thing2);
 }
}

O uso de globais não é realmente bom e, além disso - também não funciona com globais

 static class Example2_Format {
 //must have declaration in same scope
 static string some = "";
 static string thing = "";
 static string template = $"{some} - {thing}";

//This returns " - " and not "someone - something" as you would maybe 
//expect
 public static string FormatExample1() {
   some = "someone";
   thing = "something";
   return template;
 }

//This returns " - " and not "someoneelse- somethingelse" as you would 
//maybe expect
 public static string FormatExample2() {
   some = "someoneelse";
   thing = "somethingelse";
   return template;
 }
}
Tom
fonte
Essa resposta é importante, pois indica que a interpolação ocorre quando você "chama" a string $, não quando a declara.
Dx_over_dt
1
Você está certo sobre o antipadrão de declarar suas variáveis ​​de interpolação no escopo da classe; no entanto, se essas variáveis já pertencerem como propriedades da classe, esse padrão funcionará bem.
Dx_over_dt
@dx_over_dt Você está errado. Sequências interpoladas são avaliadas no momento em que são declaradas. É por isso que o código de exemplo não faz sentido. Também não será compilado.
NineBerry 04/02/19
@NineBerry Você está correto, tanto quanto as seqüências interpoladas são avaliadas no momento em que são declaradas, e sobre o Example_ $ Format não compila e o código de amostra não faz sentido :) Corrigi a amostra para explicá-la melhor.
Tom
5

Não sei como funciona, mas você também pode usá-lo para tabular seus valores!

Exemplo:

Console.WriteLine($"I can tab like {"this !", 5}.");

Claro, você pode substituir "isto!" com qualquer variável ou qualquer coisa significativa, assim como você também pode alterar a guia.

Een Amok
fonte
sim, você também pode formatar a string msdn.microsoft.com/en-us/library/dn961160.aspx
M.kazem Akhgary