Cosa significa $ prima di una stringa?


251

Stavo per usare una stringa testuale ma ho digitato per errore $invece di @.

Ma il compilatore non mi ha dato alcun errore e compilato correttamente.

Voglio sapere di cosa si tratta e cosa fa. L'ho cercato ma non sono riuscito a trovare nulla.

Tuttavia non è come una stringa testuale perché non riesco a scrivere:

string str = $"text\";

Qualcuno sa cosa significa la $stringa prima di C #.

string str = $"text";

Sto usando Visual Studio 2015 CTP.

Risposte:


419

$è una scorciatoia per String.Formated è usato con interpolazioni di stringhe, che è una nuova funzionalità di C # 6. Come usato nel tuo caso, non fa nulla, proprio come string.Format()non farebbe nulla.

Viene in sé quando viene utilizzato per costruire stringhe con riferimento ad altri valori. Ciò che prima doveva essere scritto come:

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

Ora diventa:

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

Esiste anche un'alternativa - meno nota - la forma di interpolazione delle stringhe $@ (l'ordine dei due simboli è importante). Consente di @""mescolare le funzionalità di una stringa per $""supportare le interpolazioni di stringa senza la necessità di utilizzare l' \\intera stringa. Quindi le seguenti due righe:

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

produrrà:

c:\a\b\c

29
Si noti che non utilizza realmente String.Format, ma è una funzionalità basata sul compilatore, non di runtime.
Shahar Prish,

2
Nota minore che ho imparato oggi, se usi $@, quindi sei costretto a scappare dal "personaggio usando "". Questo non è il caso quando si utilizza solo $.
Flater,

3
@Flater Non ha nulla a che fare con il simbolo $. È lo stesso comportamento di prima dell'esistenza del simbolo $.
BVernon

2
Per quanto riguarda l'ordinamento dei simboli verbatim (@) e interpolazione ($) essendo importante, questo viene corretto in C # 8 in modo che l'ordine non abbia più importanza. Vedi: devsanon.com/uncategorized/…
elkaz

39

Crea una stringa interpolata .

Da MSDN

Utilizzato per costruire stringhe. Un'espressione di stringa interpolata si presenta come una stringa di modello che contiene espressioni. Un'espressione di stringa interpolata crea una stringa sostituendo le espressioni contenute con le rappresentazioni ToString dei risultati delle espressioni.

es:

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

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

È possibile utilizzare espressioni all'interno della stringa interpolata

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

La cosa bella è che non devi preoccuparti dell'ordine dei parametri come fai con te String.Format.

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

Ora se vuoi rimuovere alcuni parametri devi andare e aggiornare tutti i conteggi, il che non è più il caso.

Nota che il buon vecchio string.formatè ancora rilevante se vuoi specificare informazioni culturali nella tua formattazione .


Nota che probabilmente potresti ancora usare $e specificare le informazioni sulla cultura se converti i tuoi dati in stringa all'interno $dell'espressione usando la cultura corretta, ad es {somevar.ToString(...,[Insert culture info here])}.
jrh

18

Codice di esempio

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}");

Produzione

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

Sono stringhe interpolate . È possibile utilizzare una stringa interpolata ovunque sia possibile utilizzare una stringa letterale. Quando si esegue il programma, il codice viene eseguito con il valore letterale della stringa interpolata, il codice calcola un nuovo valore letterale della stringa valutando le espressioni di interpolazione. Questo calcolo si verifica ogni volta che viene eseguito il codice con la stringa interpolata.

L'esempio seguente produce un valore di stringa in cui sono stati calcolati tutti i valori di interpolazione di stringa. È il risultato finale e ha tipo stringa. Tutte le occorrenze di doppie parentesi graffe (“{{“ and “}}”)vengono convertite in una singola parentesi graffa.

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

Dopo aver eseguito sopra 2 righe, la variabile messagecontiene "Hello, World".

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

Riferimento - MSDN


10

Funzionalità interessante. Voglio solo sottolineare l'enfasi sul perché questo è meglio di string.format se non è evidente ad alcune persone.

Ho letto qualcuno dire ordine string.format a "{0} {1} {2}" per abbinare i parametri. Non sei obbligato a ordinare "{0} {1} {2}" in string.format, puoi anche fare "{2} {0} {1}". Tuttavia, se hai molti parametri, come 20, vuoi davvero sequenziare la stringa su "{0} {1} {2} ... {19}". Se si tratta di un pasticcio mischiato, sarà difficile allineare i parametri.

Con $, puoi aggiungere parametri in linea senza contare i tuoi parametri. Questo rende il codice molto più facile da leggere e gestire.

Il rovescio della medaglia di $ è, non è possibile ripetere facilmente il parametro nella stringa, è necessario digitarlo. Ad esempio, se sei stanco di digitare System.Environment.NewLine, puoi fare string.format ("... {0} ... {0} ... {0}", System.Environment.NewLine), ma, in $, devi ripeterlo. Non puoi fare $ "{0}" e passarlo a string.format perché $ "{0}" restituisce "0".

Nella nota a margine, ho letto un commento in un altro tpoic duplicato. Non ho potuto commentare, quindi eccolo qui. Lui ha detto che

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

crea più di un oggetto stringa. Questo non è vero in realtà. Se lo fai in una sola riga, crea solo una stringa e viene inserita nella cache delle stringhe.

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

Tutti restituiscono una stringa e creano solo un valore nella cache.

D'altro canto:

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

Crea 4 valori diversi nella cache perché ci sono 4 ";".

Pertanto, sarà più facile scrivere codice come il seguente, ma creeresti cinque stringhe interpolate quando Carlos Muñoz correggesse:

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

Questo crea una singola stringa nella cache mentre hai un codice molto facile da leggere. Non sono sicuro delle prestazioni, ma sono sicuro che MS lo ottimizzerà se non lo fa già.


1
Il tuo ultimo esempio è sbagliato: in realtà stai creando due stringhe: una dalla stringa interpolata e l'altra dal resto delle stringhe. Si noti che solo quello con {myName} è interpolato, gli altri non funzionano come previsto.
Carlos Muñoz,

1
E se anteponi $ alle 5 stringhe crea 5 stringhe interpolate ognuna con la propria String.Format()e quindi concatenata in fase di esecuzione con String.Concat. Quindi è meglio non dividerlo in più righe
Carlos Muñoz,

1
Hai ragione @Carlos Muñoz, l'ho corretto. Grazie per aver colto l'errore.
BoBoDev

8

Nota che puoi anche combinare i due, il che è piuttosto interessante (anche se sembra un po 'strano):

// simple interpolated verbatim string
WriteLine($@"Path ""C:\Windows\{file}"" not found.");

5
Se solo potessi decidere l'ordine in cui hai digitato $@o @$. Sfortunatamente può essere solo$@
Bauss il

2
@Bauss Questo ha senso. @definisce come rappresentare la stringa letterale. $è una scorciatoia per string.Format. Pensalo come$(@"");
marsze il

Non è davvero una scorciatoia per string.Format. È zuccheroso nel presentare un valore che viene analizzato in a string.Format, quindi ha parzialmente senso, ma non del tutto.
Bauss,

3
Sto solo dicendo che $è fondamentalmente una chiamata di funzione implicita mentre @fa parte del letterale, proprio come min un letterale decimale. Ecco perché esiste un solo ordine logico.
Marsze

2
So che questo è stato principalmente qui solo per dimostrare $, ma per la massima compatibilità e non per la codifica rigida se il separatore di directory è '/' o '\', e anche per evitare l'inevitabile errore che provoca una doppia barra o una barra mancante dove dovrebbe esserci sono stato uno, ti consiglio di usare Path.Combine()invece di usare le concatenazioni di stringhe quando lavori con directory e file.
jrh

6

È più conveniente di string.Format e puoi usare anche intellisense qui.

inserisci qui la descrizione dell'immagine

Ed ecco il mio metodo di prova:

[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);
}

6

Significa interpolazione di stringhe.

Ti proteggerà perché aggiunge la protezione del tempo di compilazione alla valutazione della stringa.

Non otterrai più un'eccezione con string.Format("{0}{1}",secondParamIsMissing)


6

L'esempio seguente evidenzia vari vantaggi dell'utilizzo di stringhe interpolate per string.Format()quanto riguarda pulizia e leggibilità. Mostra anche che il codice all'interno {}viene valutato come qualsiasi altro argomento di funzione, proprio come farebbe se string.Format()venissimo chiamato.

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.

6

La sintassi $ è buona, ma con un lato negativo.

Se hai bisogno di qualcosa come un modello di stringa, che viene dichiarato a livello di classe come campo ... bene in un posto come dovrebbe essere.

Quindi devi dichiarare le variabili sullo stesso livello ... il che non è proprio bello.

È molto più bello usare la stringa. Sintassi formattata per questo tipo di cose

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);
 }
}

L'uso dei globi non è davvero ok e oltre a ciò - non funziona neanche con i globi

 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;
 }
}

Questa risposta è importante in quanto sottolinea che l'interpolazione si verifica quando si "chiama" la stringa $, non quando la si dichiara.
dx_over_dt

1
Hai ragione sull'anti-schema di dichiarare le tue variabili di interpolazione nell'ambito della classe, tuttavia se quelle variabili appartengono già come proprietà della classe, questo schema funziona bene.
dx_over_dt

@dx_over_dt Ti sbagli. Le stringhe interpolate vengono valutate nel momento in cui vengono dichiarate. Ecco perché il codice di esempio non ha senso. Inoltre non verrà compilato.
NineBerry

@NineBerry Hai ragione sia sulle stringhe interpolate che vengono valutate nel momento in cui sono dichiarate che su Esempio_ $ Il formato non viene compilato e il codice di esempio non ha senso :) Ho corretto l'esempio per spiegarlo meglio.
Tom,


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.