¿Cuál es la diferencia entre una cadena normal y una cadena literal?

166

Tengo una versión de prueba de Resharper y siempre sugiere que cambie las cadenas regulares a cadenas literales. ¿Cuál es la diferencia?

Xaisoft
fuente
3
Nunca he visto esta sugerencia de ReSharper. ¿Puedes dar un ejemplo donde sugiera esto?
John Saunders
3
Lo acabo de obtener. La primera sugerencia fue moverlo a un recurso, pero la segunda fue convertirlo en una cadena literal: MessageBox.Show ("Un ornitorrinco debe ser acariciado antes de que el trabajo pueda continuar");
B. Clay Shannon
Todavía lo entiendo todo el tiempo. Por lo general, es una de las advertencias de reafilador que desea desactivar, ya que sugiere hacer que las cadenas sean textuales sin ningún motivo.
Dean Swiatek
Si le gusta mi característica sugerida para el IDE de Visual Studio, vote a favor aquí: developercommunity.visualstudio.com/idea/602807/…
Olivier Jacot-Descombes

Respuestas:

191

Una cadena literal es aquella que no necesita escapar, como un nombre de archivo:

string myFileName = "C:\\myfolder\\myfile.txt";

sería

string myFileName = @"C:\myfolder\myfile.txt";

El símbolo @ significa leer esa cadena literalmente, y no interpretar los caracteres de control de otra manera.

alc6379
fuente
12
Me pregunto por qué Resharper sugiere este cambio. ¿Algún gurú de CLR sabe si las cadenas literales se procesan de manera más eficiente ya que se pueden ignorar los caracteres de escape?
Matt Peterson el
9
Creo que quizás ReSharper lo sugiere porque la cadena literal es más legible.
andyp
36
Creo que es una especie de convención de codificación (nunca la había visto ni oído antes). Para las cadenas, ReSharper sugiere moverlo a un archivo de recursos para su localización o hacerlo literalmente; para las cadenas literales, ReSharper ya no ofrece la opción de localizar la cadena. Por lo tanto, parece una convención hacer que todas las cadenas que no necesitan localización sean textuales.
Daniel Brückner
Digamos que tenemos un literal de cadena asignado a la variable de cadena, string myFileName = "C: \\ myfolder \\ myfile.txt"; Ahora, quiero convertir la variable de cadena myFileName en una cadena literal. ¿Cómo lo hago? ¿Esto funciona? string verbatimStr = @myFileName;
sanjeev bhusal
3
@sanjeevbhusal: Realmente nunca haces eso. @ "C: \ myfolder \ myfile.txt" y "C: \\ myfolder \\ myfile.txt" son lo mismo para el CLR. Es solo azúcar sintáctico, básicamente.
alc6379
68

Esto está cubierto en la sección 2.4.4.5 de la especificación C # :

2.4.4.5 Literales de cadena

C # admite dos formas de literales de cadena: literales de cadena regulares y literales de cadena literales.

Un literal de cadena regular consta de cero o más caracteres encerrados entre comillas dobles, como en "hola", y puede incluir tanto secuencias de escape simples (como \ t para el carácter de tabulación) como secuencias de escape hexadecimales y Unicode.

Un literal de cadena literal consiste en un carácter @ seguido de un carácter de comillas dobles, cero o más caracteres y un carácter de comillas dobles de cierre. Un ejemplo simple es @ "hola". En una cadena literal literal, los caracteres entre los delimitadores se interpretan literalmente, la única excepción es una secuencia de escape entre comillas. En particular, las secuencias de escape simples y las secuencias de escape hexadecimales y Unicode no se procesan en literales de cadena literales. Un literal de cadena literal puede abarcar varias líneas.

En otras palabras, el único carácter especial en un @ "literal literal de cadena" es el carácter de comillas dobles. Si desea escribir una cadena literal que contenga comillas dobles, debe escribir dos comillas dobles. Todos los demás personajes se interpretan literalmente.

Incluso puede tener nuevas líneas literales en una cadena literal literal. En un literal de cadena normal no puede tener nuevas líneas literales. En su lugar, debe usar, por ejemplo "\n".

Los literales de cadenas literales a menudo son útiles para incrustar nombres de archivo y expresiones regulares en el código fuente, porque las barras invertidas en este tipo de cadenas son comunes y tendrían que escaparse si se usara un literal de cadena regular.

No hay diferencia en el tiempo de ejecución entre las cadenas creadas a partir de literales de cadena regulares y las cadenas creadas a partir de literales de cadena textuales: ambas son de tipo System.String.

Mark Byers
fuente
27

No hay diferencia de tiempo de ejecución entre una cadena y una cadena literal. Solo son diferentes en tiempo de compilación. El compilador acepta menos secuencias de escape en una cadena literal, por lo que lo que ves es lo que obtienes que no sea un escape de comillas.

También puede usar el carácter literal, @, para indicarle al compilador que trate una palabra clave como un nombre:

var @if = "if";
//okay, treated as a name
Console.WriteLine(@if);
//compiler err, if without @ is a keyword
Console.WriteLine(if);

var @a = "a";
//okay
Console.WriteLine(@a);
//also okay, @ isn't part of the name
Console.WriteLine(a);
Corbin March
fuente
16

También puede tener una cadena multilínea usando cadenas literales:

Console.WriteLine(@"This
    is
    a
    Test
    for stackoverflow");

sin @que tengas un error

En VB14 hay una nueva característica llamada Multiline Strings, es como cadenas literales en C #.

Cuerdas Multilínea

Consejo profesional: los literales de cadena VB ahora son exactamente como las cadenas textuales de C #.

Mohamad Shiralizadeh
fuente
13

Las cadenas regulares usan secuencias de escape especiales para traducir a caracteres especiales.

/*
This string contains a newline
and a tab    and an escaped backslash\
*/
Console.WriteLine("This string contains a newline\nand a tab\tand an escaped backslash\\");

Las cadenas literales se interpretan tal cual, sin traducir ninguna secuencia de escape:

/* 
This string displays as is. No newlines\n, tabs\t or backslash-escapes\\.
*/
Console.WriteLine(@"This string displays as is. No newlines\n, tabs\t or backslash-escapes\\.");
BoltClock
fuente
0

Si desea eliminar las advertencias de Resharper, puede usar:

Localizable(false)

Para cosas como parámetros, ubicaciones de archivos, por ejemplo. Esta podría ser una buena solución.

AndyO
fuente