¿Hay una manera fácil de crear un literal de cadena multilínea en C #?
Esto es lo que tengo ahora:
string query = "SELECT foo, bar"
+ " FROM table"
+ " WHERE id = 42";
Sé que PHP tiene
<<<BLOCK
BLOCK;
¿C # tiene algo similar?
Puede usar el @
símbolo delante de a string
para formar un literal de cadena literal :
string query = @"SELECT foo, bar
FROM table
WHERE id = 42";
También no tiene que escapar caracteres especiales cuando se utiliza este método, a excepción de las comillas dobles como se muestra en la respuesta de Jon Skeet.
@"my string".Replace(Environment.NewLine, "")
Se llama literal literal de cadena en C #, y es solo una cuestión de poner @ antes del literal. Esto no solo permite varias líneas, sino que también desactiva el escape. Entonces, por ejemplo, puedes hacer:
string query = @"SELECT foo, bar
FROM table
WHERE name = 'a\b'";
Sin embargo, esto incluye los saltos de línea (usando cualquier salto de línea que su fuente los tenga) en la cadena. Para SQL, eso no solo es inofensivo, sino que probablemente mejore la legibilidad en cualquier lugar donde vea la cadena, sino que en otros lugares puede que no sea necesario, en cuyo caso no necesitará usar un literal de cadena literal de varias líneas para comenzar, o eliminarlos de la cadena resultante.
La única escapatoria es que si desea una comilla doble, debe agregar un símbolo extra de comillas dobles:
string quote = @"Jon said, ""This will work,"" - and it did!";
El problema con el uso del literal de cadena que encuentro es que puede hacer que su código se vea un poco " extraño " porque para no obtener espacios en la cadena en sí, debe alinearse completamente a la izquierda:
var someString = @"The
quick
brown
fox...";
Yuck
Entonces, la solución que me gusta usar, que mantiene todo bien alineado con el resto de su código es:
var someString = String.Join(
Environment.NewLine,
"The",
"quick",
"brown",
"fox...");
Y, por supuesto, si lo que desea dividir lógicamente las líneas de una instrucción SQL como eres y en realidad no necesita una nueva línea, siempre puede sustituir Environment.NewLine
por " "
.
Otra cosa que debes observar es el uso de literales de cadena en string.Format. En ese caso, debe escapar de llaves / llaves '{' y '}'.
// this would give a format exception
string.Format(@"<script> function test(x)
{ return x * {0} } </script>", aMagicValue)
// this contrived example would work
string.Format(@"<script> function test(x)
{{ return x * {0} }} </script>", aMagicValue)
Como nota al margen, con C # 6.0 ahora puede combinar cadenas interpoladas con el literal de cadena literal:
string camlCondition = $@"
<Where>
<Contains>
<FieldRef Name='Resource'/>
<Value Type='Text'>{(string)parameter}</Value>
</Contains>
</Where>";
$@"{{example literal text { fooString }. }}"
esto puede confundir a algunos porque Angular, React y Vue.js usan la convención opuesta.
¿Por qué las personas siguen confundiendo cadenas con literales de cadena? La respuesta aceptada es una gran respuesta a una pregunta diferente; no a este
Sé que este es un tema antiguo, pero vine aquí posiblemente con la misma pregunta que el OP, y es frustrante ver cómo la gente sigue interpretándolo mal. O tal vez lo estoy leyendo mal, no lo sé.
En términos generales, una cadena es una región de la memoria de la computadora que, durante la ejecución de un programa, contiene una secuencia de bytes que pueden asignarse a caracteres de texto. Un literal de cadena, por otro lado, es una pieza de código fuente, aún no compilada, que representa el valor utilizado para inicializar una cadena más adelante, durante la ejecución del programa en el que aparece.
En C #, la declaración ...
string query = "SELECT foo, bar"
+ " FROM table"
+ " WHERE id = 42";
... no produce una cadena de tres líneas sino un trazador de líneas; la concatenación de tres cadenas (cada una inicializada de un literal diferente) ninguna de las cuales contiene un modificador de nueva línea.
Lo que el OP parece estar preguntando, al menos lo que estaría preguntando con esas palabras, no es cómo introducir, en la cadena compilada, saltos de línea que imitan a los que se encuentran en el código fuente, sino cómo separarlos para mayor claridad. , una sola línea de texto en el código fuente sin introducir saltos en la cadena compilada. Y sin requerir un tiempo de ejecución prolongado, pasó uniéndose a las múltiples subcadenas que provienen del código fuente. Al igual que las barras invertidas finales dentro de un literal de cadena multilínea en javascript o C ++.
Sugerir el uso de cadenas literales, no importa StringBuilder
s , so String.Join
incluso funciones anidadas con reversiones de cadenas y qué no, me hace pensar que la gente realmente no comprende la pregunta. O tal vez no lo entiendo.
Hasta donde yo sé, C # no tiene (al menos en la versión paleolítica que todavía estoy usando, de la década anterior) una característica para producir limpiamente literales de cadena multilínea que se puedan resolver durante la compilación en lugar de la ejecución.
Tal vez las versiones actuales sí lo admiten, pero pensé que compartiría la diferencia que percibo entre cadenas y literales de cadena.
ACTUALIZAR:
(Del comentario de MeowCat2012) Puedes. El enfoque "+" de OP es el mejor. Según las especificaciones, la optimización está garantizada: http://stackoverflow.com/a/288802/9399618
No he visto esto, así que lo publicaré aquí (si está interesado en pasar una cadena, también puede hacerlo). La idea es que puede dividir la cadena en varias líneas y agregar su propio contenido (también en varias líneas) de la forma que desee. Aquí "tableName" se puede pasar a la cadena.
private string createTableQuery = "";
void createTable(string tableName)
{
createTableQuery = @"CREATE TABLE IF NOT EXISTS
["+ tableName + @"] (
[ID] INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
[Key] NVARCHAR(2048) NULL,
[Value] VARCHAR(2048) NULL
)";
}
createTable("MyTable");
en cualquier caso, la pregunta del OP fue sobre cómo ingresar literales de cadena multilínea directamente en el código , no cómo construir consultas de base de datos per se. :)
Puedes usar @ y "" .
string sourse = @"{
""items"":[
{
""itemId"":0,
""name"":""item0""
},
{
""itemId"":1,
""name"":""item1""
}
]
}";
Sí, puede dividir una cadena en varias líneas sin introducir nuevas líneas en la cadena real, pero no es bonito:
string s = $@"This string{
string.Empty} contains no newlines{
string.Empty} even though it is spread onto{
string.Empty} multiple lines.";
El truco consiste en introducir código que se evalúe como vacío, y ese código puede contener nuevas líneas sin afectar la salida. Adapte este enfoque de esta respuesta a una pregunta similar.
Aparentemente existe cierta confusión sobre cuál es la pregunta, pero hay dos pistas de que lo que queremos aquí es un literal de cadena que no contenga caracteres de nueva línea, cuya definición abarque varias líneas. (en los comentarios lo dice, y "esto es lo que tengo" muestra código que no crea una cadena con nuevas líneas)
Esta prueba unitaria muestra la intención:
[TestMethod]
public void StringLiteralDoesNotContainSpaces()
{
string query = "hi"
+ "there";
Assert.AreEqual("hithere", query);
}
Cambie la definición anterior de consulta para que sea un literal de cadena, en lugar de la concatenación de dos literales de cadena que el compilador puede o no optimizar en uno.
El enfoque de C ++ consistiría en finalizar cada línea con una barra diagonal inversa, haciendo que el carácter de nueva línea se escape y no aparezca en la salida. Desafortunadamente, todavía existe el problema de que cada línea después de la primera debe dejarse alineada para no agregar espacios en blanco adicionales al resultado.
Solo hay una opción que no se basa en optimizaciones del compilador que podrían no suceder, que es poner su definición en una línea. Si desea confiar en las optimizaciones del compilador, el + que ya tiene es excelente; no tiene que alinear a la izquierda la cadena, no obtiene nuevas líneas en el resultado, y es solo una operación, sin llamadas de función, para esperar la optimización.
Agregue varias líneas: use @
string query = @"SELECT foo, bar
FROM table
WHERE id = 42";
Agregue valores de cadena al medio: use $
string text ="beer";
string query = $"SELECT foo {text} bar ";
Cadena de línea múltiple Agregue valores al medio: use $ @
string text ="Customer";
string query = $@"SELECT foo, bar
FROM {text}Table
WHERE id = 42";
Si no desea espacios / líneas nuevas, la adición de cadenas parece funcionar:
var myString = String.Format(
"hello " +
"world" +
" i am {0}" +
" and I like {1}.",
animalType,
animalPreferenceType
);
// hello world i am a pony and I like other ponies.
Puede ejecutar lo anterior aquí si lo desea.
Sé que llego un poco tarde a la fiesta, pero quiero recomendar https://www.buildmystring.com/ para futuros lectores de este hilo. Puede convertir cualquier código a literal de cadena C # usando este sitio.
Puede usar estos dos métodos:
private static String ReverseString(String str)
{
int word_length = 0;
String result = "";
for (int i = 0; i < str.Length; i++)
{
if (str[i] == ' ')
{
result = " " + result;
word_length = 0;
}
else
{
result = result.Insert(word_length, str[i].ToString());
word_length++;
}
}
return result;
}
//NASSIM LOUCHANI
public static string SplitLineToMultiline(string input, int rowLength)
{
StringBuilder result = new StringBuilder();
StringBuilder line = new StringBuilder();
Stack<string> stack = new Stack<string>(ReverseString(input).Split(' '));
while (stack.Count > 0)
{
var word = stack.Pop();
if (word.Length > rowLength)
{
string head = word.Substring(0, rowLength);
string tail = word.Substring(rowLength);
word = head;
stack.Push(tail);
}
if (line.Length + word.Length > rowLength)
{
result.AppendLine(line.ToString());
line.Clear();
}
line.Append(word + " ");
}
result.Append(line);
return result.ToString();
}
En SplitLineToMultiline (), debe definir la cadena que desea usar y la longitud de la fila, es muy simple. Gracias .
42
como parámetro, especialmente si proviene de la entrada del usuario, para evitar la inyección de SQL.