Was bedeutet $ vor einem String?

250

Ich wollte wörtlich Zeichenfolge verwenden , aber ich getippt fälschlicherweise $statt@ .

Aber der Compiler hat mir keinen Fehler gegeben und erfolgreich kompiliert.

Ich möchte wissen, was es ist und was es tut. Ich habe danach gesucht, aber ich konnte nichts finden.

Es ist jedoch nicht wie eine wörtliche Zeichenfolge, weil ich nicht schreiben kann:

string str = $"text\";

Weiß jemand, wofür $vor String in C # steht?

string str = $"text";

Ich verwende Visual Studio 2015 CTP.

M. kazem Akhgary
quelle

Antworten:

418

$ist eine Abkürzung für String.Formatund wird mit String-Interpolationen verwendet, was eine neue Funktion von C # 6 ist. Wie in Ihrem Fall verwendet, macht es nichts, genauso wiestring.Format() es nichts tun würde.

Es kommt zur Geltung, wenn Zeichenfolgen mit Bezug auf andere Werte erstellt werden. Was vorher geschrieben werden musste als:

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

Jetzt wird:

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

Es gibt auch eine alternative - weniger bekannte - Form der String-Interpolation mit $@ (die Reihenfolge der beiden Symbole ist wichtig). Damit können die Funktionen eines @""Strings gemischt werden $"", um String-Interpolationen zu unterstützen, ohne dass der \\gesamte String benötigt wird. Also die folgenden zwei Zeilen:

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

wird ausgegeben:

c:\a\b\c
David Arno
quelle
29
Beachten Sie, dass String.Format nicht wirklich verwendet wird, sondern eine compilerbasierte Funktion ist, keine Laufzeitfunktion.
Shahar Prish
2
Kleinere Anmerkung, die ich heute gelernt habe, wenn Sie verwenden $@, dann sind Sie gezwungen, dem "Charakter zu entkommen , indem Sie verwenden "". Dies ist nicht der Fall, wenn Sie nur verwenden $.
Flater
3
@Flater Das hat aber nichts mit dem $ -Symbol zu tun. Das ist das gleiche Verhalten wie vor dem $ -Symbol.
BVernon
2
Da die Reihenfolge der Reihenfolge der wörtlichen (@) und Interpolationssymbole ($) wichtig ist, wird dies in C # 8 korrigiert, sodass die Reihenfolge keine Rolle mehr spielt. Siehe: devsanon.com/uncategorized/…
elkaz
38

Es wird eine interpolierte Zeichenfolge erstellt .

Von MSDN

Wird zum Erstellen von Zeichenfolgen verwendet. Ein interpolierter Zeichenfolgenausdruck sieht aus wie eine Vorlagenzeichenfolge, die Ausdrücke enthält. Ein interpolierter Zeichenfolgenausdruck erstellt eine Zeichenfolge, indem die enthaltenen Ausdrücke durch die ToString-Repräsentationen der Ergebnisse der Ausdrücke ersetzt werden.

Ex :

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

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

Sie können Ausdrücke innerhalb der interpolierten Zeichenfolge verwenden

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

Das Schöne daran ist, dass Sie sich nicht um die Reihenfolge der Parameter kümmern müssen, wie Sie es tun String.Format.

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

Wenn Sie nun einige Parameter entfernen möchten, müssen Sie alle Zählungen aktualisieren, was nicht mehr der Fall ist.

Beachten Sie, dass das gute Alte string.formatimmer noch relevant ist, wenn Sie kulturelle Informationen in Ihrer Formatierung angeben möchten .

Sleiman Jneidi
quelle
Beachten Sie, dass Sie wahrscheinlich weiterhin $Kulturinformationen verwenden und angeben können, wenn Sie Ihre Daten $mit der richtigen Kultur in eine Zeichenfolge innerhalb des Ausdrucks konvertieren , z {somevar.ToString(...,[Insert culture info here])}.
jrh
18

Beispielcode

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

Ausgabe

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

Es ist Interpolated Strings . Sie können eine interpolierte Zeichenfolge überall dort verwenden, wo Sie ein Zeichenfolgenliteral verwenden können. Wenn Ihr Programm den Code mit dem interpolierten Zeichenfolgenliteral ausführt, berechnet der Code ein neues Zeichenfolgenliteral, indem er die Interpolationsausdrücke auswertet. Diese Berechnung erfolgt jedes Mal, wenn der Code mit der interpolierten Zeichenfolge ausgeführt wird.

Das folgende Beispiel erzeugt einen Zeichenfolgenwert, bei dem alle Zeichenfolgeninterpolationswerte berechnet wurden. Es ist das Endergebnis und hat eine Typzeichenfolge. Alle Vorkommen von doppelten geschweiften Klammern (“{{“ and “}}”)werden in eine einzelne geschweifte Klammer umgewandelt.

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

Nach der Ausführung über 2 Zeilen messageenthält die Variable "Hallo, Welt".

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

Referenz - MSDN

Saveendra Ekanayake
quelle
10

Coole Funktion. Ich möchte nur darauf hinweisen, warum dies besser ist als string.format, wenn es einigen Leuten nicht klar ist.

Ich habe jemanden gelesen, der order string.format zu "{0} {1} {2}" sagt, um den Parametern zu entsprechen. Sie müssen "{0} {1} {2}" nicht in string.format bestellen, sondern können auch "{2} {0} {1}" ausführen. Wenn Sie jedoch viele Parameter haben, z. B. 20, möchten Sie die Zeichenfolge wirklich auf "{0} {1} {2} ... {19}" setzen. Wenn es sich um ein gemischtes Durcheinander handelt, fällt es Ihnen schwer, Ihre Parameter in eine Reihe zu bringen.

Mit $ können Sie Parameter inline hinzufügen, ohne Ihre Parameter zu zählen. Dies erleichtert das Lesen und Verwalten des Codes erheblich.

Der Nachteil von $ ist, dass Sie den Parameter in der Zeichenfolge nicht einfach wiederholen können, sondern ihn eingeben müssen. Wenn Sie beispielsweise die Eingabe von System.Environment.NewLine satt haben, können Sie string.format ("... {0} ... {0} ... {0}", System.Environment.NewLine) ausführen. aber in $ müssen Sie es wiederholen. Sie können $ "{0}" nicht ausführen und an string.format übergeben, da $ "{0}" "0" zurückgibt.

Nebenbei habe ich einen Kommentar in einem anderen duplizierten tpoic gelesen. Ich konnte es nicht kommentieren, also hier ist es. Er hat das gesagt

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

Erstellt mehr als ein String-Objekt. Das ist eigentlich nicht wahr. Wenn Sie dies in einer einzelnen Zeile tun, wird nur eine Zeichenfolge erstellt und im Zeichenfolgencache abgelegt.

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

Alle geben eine Zeichenfolge zurück und erstellen nur einen Wert im Cache.

Andererseits:

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

Erstellt 4 verschiedene Werte im Cache, da 4 ";" vorhanden sind.

Somit ist es einfacher, Code wie den folgenden zu schreiben, aber Sie würden fünf interpolierte Zeichenfolgen erstellen, wenn Carlos Muñoz korrigiert:

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

Dadurch wird eine einzelne Zeichenfolge im Cache erstellt, während Sie den Code sehr einfach lesen können. Ich bin mir über die Leistung nicht sicher, aber ich bin sicher, dass MS sie optimieren wird, wenn sie es nicht bereits tut.

BoBoDev
quelle
1
Ihr letztes Beispiel ist falsch: Tatsächlich erstellen Sie zwei Zeichenfolgen: eine aus der interpolierten Zeichenfolge und eine aus dem Rest der Zeichenfolgen. Beachten Sie, dass nur der mit {myName} interpoliert wird, die anderen funktionieren nicht wie erwartet.
Carlos Muñoz
1
Wenn Sie den 5 Zeichenfolgen $ voranstellen, werden 5 interpolierte Zeichenfolgen mit jeweils eigenen Zeichenfolgen erstellt String.Format()und zur Laufzeit mit verkettet String.Concat. Es ist also besser, dass Sie es nicht in mehrere Zeilen aufteilen
Carlos Muñoz
1
Sie haben Recht @Carlos Muñoz, ich habe es korrigiert. Vielen Dank, dass Sie den Fehler entdeckt haben.
BoBoDev
8

Beachten Sie, dass Sie auch beide kombinieren können, was ziemlich cool ist (obwohl es etwas seltsam aussieht):

// simple interpolated verbatim string
WriteLine($@"Path ""C:\Windows\{file}"" not found.");
Marsze
quelle
5
Wenn Sie nur entscheiden könnten, in welcher Reihenfolge Sie tippen $@oder @$. Leider kann es nur sein$@
Bauss
2
@Bauss Das macht Sinn. @definiert, wie das String-Literal dargestellt wird. $ist eine Abkürzung für string.Format. $(@"");
Betrachten
Es ist nicht wirklich eine Abkürzung für string.Format. Es ist zuckerhaltig, um einen Wert zu präsentieren, der auf a analysiert wird. Daher string.Formatist es teilweise sinnvoll, aber nicht vollständig.
Bauss
3
Ich sage nur, dass $es sich im Grunde genommen um einen impliziten Funktionsaufruf handelt, während er @Teil des Literal ist, genau wie der min einem Dezimalliteral. Deshalb gibt es nur eine logische Reihenfolge.
Marsze
2
Ich weiß, dass dies meistens nur hier war, um zu demonstrieren $, aber aus Gründen der maximalen Kompatibilität und nicht der harten Codierung, ob das Verzeichnis-Trennzeichen '/' oder '\' ist, und um zu vermeiden, dass der unvermeidliche Fehler einen doppelten Schrägstrich oder einen fehlenden Schrägstrich verursacht, wo es sein sollte Ich empfehle, Path.Combine()bei der Arbeit mit Verzeichnissen und Dateien anstelle von Zeichenfolgenverkettungen zu verwenden.
jrh
6

Es ist bequemer als string.Format und Sie können auch hier Intellisense verwenden.

Geben Sie hier die Bildbeschreibung ein

Und hier ist meine Testmethode:

[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
quelle
6

Es bedeutet String-Interpolation.

Es schützt Sie, da es der Zeichenfolgenbewertung einen Schutz für die Kompilierungszeit hinzufügt.

Sie erhalten keine Ausnahme mehr mit string.Format("{0}{1}",secondParamIsMissing)

Silber
quelle
6

Das folgende Beispiel zeigt verschiedene Vorteile der Verwendung interpolierter Zeichenfolgen in string.Format()Bezug auf Sauberkeit und Lesbarkeit. Es zeigt auch, dass Code in {}wie jedes andere Funktionsargument ausgewertet wird, genau wie wenn string.Format()wir aufgerufen würden.

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
quelle
6

$ Syntax ist nett, aber mit einem Nachteil.

Wenn Sie so etwas wie eine Zeichenfolgenvorlage benötigen, wird diese auf Klassenebene als Feld deklariert ... genau an einem Ort, wie es sein sollte.

Dann müssen Sie die Variablen auf derselben Ebene deklarieren ... was nicht wirklich cool ist.

Es ist viel schöner, die String.Format-Syntax für diese Art von Dingen zu verwenden

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

Die Verwendung von Globals ist nicht wirklich in Ordnung und außerdem funktioniert es auch nicht mit Globals

 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
quelle
Diese Antwort ist wichtig, da sie darauf hinweist, dass die Interpolation erfolgt, wenn Sie den $ -String "aufrufen", nicht, wenn Sie ihn deklarieren.
dx_over_dt
1
Sie haben Recht mit dem Anti-Muster, Ihre Interpolationsvariablen im Klassenbereich zu deklarieren. Wenn diese Variablen jedoch bereits als Klasseneigenschaften gehören , funktioniert dieses Muster gut.
dx_over_dt
@dx_over_dt Du liegst falsch. Interpolierte Zeichenfolgen werden zum Zeitpunkt ihrer Deklaration ausgewertet. Deshalb macht der Beispielcode keinen Sinn. Es wird auch nicht kompiliert.
NineBerry
@NineBerry Sie haben Recht, dass sowohl interpolierte Zeichenfolgen zum Zeitpunkt ihrer Deklaration ausgewertet werden als auch Beispiel_ $ Format nicht kompiliert wird und Beispielcode keinen Sinn ergibt :) Ich habe das Beispiel korrigiert, um es besser zu erklären.
Tom
5

Ich weiß nicht, wie es funktioniert, aber Sie können es auch verwenden, um Ihre Werte zu erfassen!

Beispiel:

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

Natürlich können Sie "dies!" mit jeder Variablen oder irgendetwas Sinnvollem, genauso wie Sie auch die Registerkarte ändern können.

Een Amok
quelle
Ja, Sie können auch die Zeichenfolge msdn.microsoft.com/en-us/library/dn961160.aspx
M.kazem Akhgary