¿Qué significa $ antes de una cadena?

251

Iba a usar una cadena literal pero escribí por error en $lugar de @.

Pero el compilador no me dio ningún error y compiló con éxito.

Quiero saber qué es y qué hace. Lo busqué pero no pude encontrar nada.

Sin embargo, no es como una cadena literal porque no puedo escribir:

string str = $"text\";

¿Alguien sabe qué significan las $cadenas antes en C #?

string str = $"text";

Estoy usando Visual studio 2015 CTP.

M.kazem Akhgary
fuente

Respuestas:

419

$es una abreviatura String.Formaty se usa con interpolaciones de cadenas, que es una nueva característica de C # 6. Como se usa en su caso, no hace nada, al igual string.Format()que no haría nada.

Se convierte en algo propio cuando se usa para construir cadenas con referencia a otros valores. Lo que antes tenía que escribirse como:

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

Ahora se convierte en:

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

También hay una forma alternativa, menos conocida, de utilizar la interpolación de cadenas $@ (el orden de los dos símbolos es importante). Permite que las características de una @""cadena se mezclen $""para admitir interpolaciones de cadena sin la necesidad de \\toda su cadena. Entonces las siguientes dos líneas:

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

dará salida:

c:\a\b\c
David Arno
fuente
29
Tenga en cuenta que en realidad no está utilizando String.Format, sino que es una característica basada en el compilador, no una en tiempo de ejecución.
Shahar Prish
2
Nota menor que aprendí hoy, si usas $@, entonces te ves obligado a escapar del "personaje usando "". Este no es el caso cuando solo se usa $.
Flater
3
@Flater Sin embargo, eso no tiene nada que ver con el símbolo $. Ese es el mismo comportamiento que tenía antes de que existiera el símbolo $.
BVernon
2
Según su punto de vista, el orden del símbolo literal (@) y el orden de interpolación ($) son importantes, esto se está corrigiendo en C # 8 para que el orden ya no importe. Ver: devsanon.com/uncategorized/…
elkaz
39

Crea una cadena interpolada .

De MSDN

Usado para construir cadenas. Una expresión de cadena interpolada se parece a una cadena de plantilla que contiene expresiones. Una expresión de cadena interpolada crea una cadena al reemplazar las expresiones contenidas con las representaciones ToString de los resultados de las expresiones.

ex:

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

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

Puedes usar expresiones dentro de la cadena interpolada

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

Lo bueno de esto es que no necesita preocuparse por el orden de los parámetros como lo hace con String.Format.

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

Ahora, si desea eliminar algunos parámetros, debe ir y actualizar todos los recuentos, lo cual ya no es el caso.

Tenga en cuenta que lo bueno string.formatsigue siendo relevante si desea especificar información cultural en su formato .

Sleiman Jneidi
fuente
Tenga en cuenta que usted podría probablemente todavía utilizar $y especificar información cultura si convierte los datos en cadena dentro de la $expresión utilizando la cultura correcta, por ejemplo, {somevar.ToString(...,[Insert culture info here])}.
jrh
18

Código de ejemplo

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

Salida

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

Se trata de cadenas interpoladas . Puede usar una cadena interpolada en cualquier lugar donde pueda usar un literal de cadena. Cuando ejecute su programa ejecutaría el código con el literal de cadena interpolado, el código calcula un nuevo literal de cadena al evaluar las expresiones de interpolación. Este cálculo ocurre cada vez que se ejecuta el código con la cadena interpolada.

El siguiente ejemplo produce un valor de cadena donde se han calculado todos los valores de interpolación de cadena. Es el resultado final y tiene tipo string. Todas las apariciones de llaves dobles (“{{“ and “}}”)se convierten en una sola llave.

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

Después de ejecutar más de 2 líneas, la variable messagecontiene "Hola, Mundo".

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

Referencia - MSDN

Saveendra Ekanayake
fuente
10

Característica genial. Solo quiero señalar el énfasis en por qué esto es mejor que string.format si no es evidente para algunas personas.

Leí a alguien diciendo orden string.format a "{0} {1} {2}" para que coincida con los parámetros. No está obligado a ordenar "{0} {1} {2}" en string.format, también puede hacer "{2} {0} {1}". Sin embargo, si tiene muchos parámetros, como 20, realmente desea secuenciar la cadena a "{0} {1} {2} ... {19}". Si se trata de un desastre aleatorio, tendrá dificultades para alinear sus parámetros.

Con $, puede agregar parámetros en línea sin contar sus parámetros. Esto hace que el código sea mucho más fácil de leer y mantener.

La desventaja de $ es que no puede repetir el parámetro en la cadena fácilmente, debe escribirlo. Por ejemplo, si está cansado de escribir System.Environment.NewLine, puede hacer string.format ("... {0} ... {0} ... {0}", System.Environment.NewLine), pero, en $, tienes que repetirlo. No puede hacer $ "{0}" y pasarlo a string.format porque $ "{0}" devuelve "0".

En la nota al margen, he leído un comentario en otra publicación duplicada. No pude comentar, así que aquí está. Él dijo que

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

crea más de una cadena de objetos. Esto no es cierto en realidad. Si hace esto en una sola línea, solo crea una cadena y se coloca en el caché de cadenas.

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

Todos ellos devuelven una cadena y solo crean un valor en el caché.

Por otra parte:

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

Crea 4 valores diferentes en el caché porque hay 4 ";".

Por lo tanto, será más fácil escribir código como el siguiente, pero crearía cinco cadenas interpoladas a medida que Carlos Muñoz corrigiera:

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

Esto crea una sola cadena en el caché mientras tiene un código muy fácil de leer. No estoy seguro del rendimiento, pero estoy seguro de que MS lo optimizará si aún no lo está haciendo.

BoBoDev
fuente
1
Su último ejemplo es incorrecto: en realidad está creando dos cadenas: una de la cadena interpolada y otra del resto de las cadenas. Tenga en cuenta que solo el que tiene {myName} se interpola, los otros no funcionan como se esperaba.
Carlos Muñoz
1
Y si antepone $ a las 5 cadenas, crea 5 cadenas interpoladas cada una con las suyas String.Format()y luego concatenadas en tiempo de ejecución con String.Concat. Así que es mejor que no lo dividas en varias líneas
Carlos Muñoz
1
Tienes razón @Carlos Muñoz, lo he corregido. Gracias por descubrir el error.
BoBoDev
8

Tenga en cuenta que también puede combinar los dos, lo cual es bastante bueno (aunque parece un poco extraño):

// simple interpolated verbatim string
WriteLine($@"Path ""C:\Windows\{file}"" not found.");
marsze
fuente
55
Si tan solo pudieras decidir el orden en que escribiste $@o @$. Desafortunadamente solo puede ser$@
Bauss
2
@Bauss Esto tiene sentido. @define cómo representar el literal de cadena. $es un acceso directo para string.Format. Piense en ello como$(@"");
marsze
No es realmente un atajo para string.Format. Es azucarado por presentar un valor que se analiza en a string.Format, por lo que tiene sentido en parte, pero no del todo.
Bauss
3
Solo digo que $es básicamente una llamada de función implícita, mientras que @es parte del literal, al igual que men un literal decimal. Por eso solo hay un orden lógico.
marsze
2
Sé que esto fue principalmente solo para demostrarlo $, pero en aras de la máxima compatibilidad y no codificar si el separador de directorios es '/' o '\', y también evitar el inevitable error que causa una doble barra o una barra faltante donde debería han sido uno, recomiendo usar en Path.Combine()lugar de usar concatenaciones de cadenas al trabajar con directorios y archivos.
jrh
6

Es más conveniente que string.Format y puede usar intellisense aquí también.

ingrese la descripción de la imagen aquí

Y aquí está mi método de prueba:

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

Significa interpolación de cadenas.

Lo protegerá porque agrega protección de tiempo de compilación en la evaluación de la cadena.

Ya no recibirá una excepción con string.Format("{0}{1}",secondParamIsMissing)

plata
fuente
6

El siguiente ejemplo resalta varias ventajas de usar cadenas interpoladas en string.Format()cuanto a limpieza y legibilidad. También muestra que el código dentro {}se evalúa como cualquier otro argumento de función, tal como lo haría si string.Format()se nos llama.

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

La sintaxis de $ es buena, pero con un inconveniente.

Si necesita algo como una plantilla de cadena, que se declara en el nivel de clase como campo ... bueno, en un lugar como debería ser.

Luego tienes que declarar las variables en el mismo nivel ... lo cual no es realmente genial.

Es mucho mejor usar la cadena. Sintaxis de formato para este tipo de cosas

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

El uso de globals no está realmente bien y además de eso, tampoco funciona con 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
fuente
Esta respuesta es importante ya que señala que la interpolación ocurre cuando "llama" a la cadena $, no cuando la declara.
dx_over_dt
1
Tiene razón sobre el antipatrón de declarar sus variables de interpolación en el ámbito de clase, sin embargo, si esas variables ya pertenecen como propiedades de clase, este patrón funciona bien.
dx_over_dt
@dx_over_dt Estás equivocado. Las cadenas interpoladas se evalúan en el momento en que se declaran. Es por eso que el código de muestra no tiene sentido. Tampoco se compilará.
NineBerry
@NineBerry Tiene razón, tanto sobre las cadenas interpoladas se evalúan en el momento en que se declaran, como sobre Example_ $ Format no se compila y sobre el código de muestra no tiene sentido :) He corregido la muestra para explicarlo mejor.
Tom
5

No sé cómo funciona, ¡pero también puedes usarlo para tabular tus valores!

Ejemplo:

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

Por supuesto, puede reemplazar "esto!" con cualquier variable o algo significativo, así como también puedes cambiar la pestaña.

Een Amok
fuente
sí, también puede formatear la cadena msdn.microsoft.com/en-us/library/dn961160.aspx
M.kazem Akhgary